8 funciones para la validación de formularios con expresiones regulares
27 de enero de 2015
Si eres desarrollador web y necesitas validar tus formularios, aquí puedes encontrar unas buenas funciones para comprobar números, cadenas de texto, direcciones de correo electrónico, direcciones web (URL), códigos postales, NIF o NIE, CIF y números de teléfono.
Una de las situaciones más comunes en el desarrollo de un formulario web se da en el momento de realizar la validación de los datos del mismo. Nombre, apellidos, dirección o población son campos que no requieren de mucha validación, puesto que, salvo necesidades mayores, suele bastar con comprobar si fueron o no fueron introducidos por el usuario.
¿Pero qué ocurre con datos como una dirección de correo electrónico, una dirección web, un número de teléfono, el código postal de una dirección o el NIF de una persona? La estructura de estos campos es mucho más específica y compleja, ya que no se trata de simples cadenas de caracteres, sino que su estructura obedece a unas reglas y patrones determinados.
Pongamos algunos ejemplos. El número de teléfono, siempre que se trate de un móvil, debe ser un número de nueve dígitos y que comience por 6 o por 7. En caso de que sea un teléfono fijo, deberá comenzar por 8 o por 9. Por su parte, el número de identificación fiscal (NIF) de una persona debe estar formado por ocho dígitos seguidos de una letra (caracter de control) que, además, no puede ser arbitraria, sino que se obtiene realizando una serie de operaciones matemáticas con los ocho dígitos anteriores.
Pues bien, para comprobar la validez este tipo de datos, tarea que no suele ser precisamente sencilla para la mayoría de desarrolladores, disponemos de una maravillosa herramienta de los lenguajes de programación: las expresiones regulares. Según la Wikipedia, una expresión regular es una secuencia de caracteres que forma un patrón de búsqueda, principalmente utilizada para la búsqueda de patrones de cadenas de caracteres u operaciones de sustituciones.
Esta entrada no está dedicada a entrar en detalles sobre las expresiones regulares o su sintáxis. Quien quiera conocer más a fondo este tema puede encontrar mucha información al respecto en la red. El objetivo de este artículo es compartir con los demás varias funciones para la validación de algunos de los campos más típicos que podemos encontrar en un formulario web.
En concreto, las funciones que hemos desarrollado permiten la validación de los siguientes tipos de datos:
Validación de un número
La siguiente función puede ser utilizada para validar un número entero mayor o igual que cero. Esta función recibe dos parámetros: el valor que se comprobará y un parámetro booleano para indicar si el cero será o no considerado como un número válido.
function es_numero($numero, $cero_valido = false) {
if (!$cero_valido) $re = '/^[1-9]+[0-9]*$/'; // {1,...,n}
else $re = '/^(0|([1-9]+[0-9]*))$/'; // {0,...,n}
return (preg_match($re, $numero));
}
Validación de una cadena de texto
Para comprobar si un campo está formado únicamente por letras de nuestro alfabeto, podemos utilizar la función que se muestra a continuación. Como se puede observar, además de los caracter alfabéticos típicos se ha añadido la letra 'Ñ', tanto en mayúscula como en minúscula, ya que se trata de un caracter especial y no está incluido en el conjunto anterior.
function es_alfabetico($c) {
$re = '/^[a-zA-ZñÑ]+$/';
return (preg_match($re, $c));
}
Validación de una dirección de correo electrónico
Una de las expresiones regulares que más quebraderos de cabeza ocasiona a los desarrolladores es la que permite verificar si una dirección de correo electrónico es válida. Para su desarrollo, hemos empleado dos expresiones regulares. La primera de ellas está extraída de jQuery Validation Plugin y prácticamente funciona por sí sola. Sin embargo, la hemos complementado con una segunda expresión regular que verifica la longitud del dominio de mayor nivel (TLD), ya que solo con la primera se considerarían válidas las direcciones de correo electrónico del tipo root@localhost.
function email_valido($email) {
$email = strtolower($email);
$re1 = '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/i';
$re2 = '/^.+@.+\.[a-z]{2,4}$/i';
return (preg_match($re1, $email) && preg_match($re2, $email));
}
Validación de una dirección web (URL)
Al igual que en la función anterior, la expresión regular utilizada para la validación de una dirección web ha sido extraída de jQuery Validation Plugin. Se trata de una expresión regular muy extensa, pero teniendo en cuentra su procedencia y los resultados de las pruebas realizadas, podemos afirmar que estamos muy satisfechos con su funcionamiento. Acepta los protocolos HTTP, HTTPS, FTP y SFTP.
function url_valido($url) {
$re = '/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])|(%[\da-f]{2})|[!\$&\'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])|(([a-z]|\d|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])([a-z]|\d|-|\.|_|~|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])*([a-z]|\d|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])))\.)+(([a-z]|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])|(([a-z]|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])([a-z]|\d|-|\.|_|~|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])*([a-z]|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])|(%[\da-f]{2})|[!\$&\'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])|(%[\da-f]{2})|[!\$&\'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])|(%[\da-f]{2})|[!\$&\'\(\)\*\+,;=]|:|@)|[\x{E000}-\x{F8FF}]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\x{00A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}])|(%[\da-f]{2})|[!\$&\'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/ui';
return (preg_match($re, $url));
}
Validación de números de teléfono
Para la validación de números de teléfono vamos a utilizar tres funciones: una para validar teléfonos fijos, otra para validar teléfonos móviles y otra para validar cualquier de ellos, sin tener en cuenta si se trata de un fijo o un móvil.
/*****************************/
/* Teléfono fijo */
/*****************************/
function fijo_valido($n) {
$re = '/^(8|9)[0-9]{8}$/';
return (preg_match($re, $n));
}
/******************************/
/* Teléfono móvil */
/******************************/
function movil_valido($n) {
$re = '/^(6|7)[0-9]{8}$/';
return (preg_match($re, $n));
}
/*************************************/
/* Teléfono fijo o móvil */
/*************************************/
function telefono_valido($n) {
return (fijo_valido($n) || movil_valido($n));
}
Validación de un código postal
Para la validación de un código postal (de España) podemos utilizar la siguiente función, que comprueba si se trata de una cadena formada únicamente por dígitos y comienza por alguno de los códigos correspondientes a las provincias de nuestro país (desde '01' hasta '52').
function cp_valido($cp) {
$re = '/^(0[1-9]|[1-4][0-9]|5[0-2])[0-9]{3}$/';
return (preg_match($re, $cp));
}
Validación de un NIF o NIE
La validación de un número de identificación fiscal (NIF) o de un número de identidad de extranjero (NIE) es un poco más complicada, ya que, además de verificar si el patrón de la cadena es válido, hay que comprobar si el dígito de control es correcto. Puedes encontrar más información en la Wikipedia.
Muchas gracias @Julia por la corrección.
function nif_valido($nif) {
$nif = strtoupper($nif);
$nifRegEx = '/^[0-9]{8}[A-Z]$/i';
$nieRegEx = '/^[XYZ][0-9]{7}[A-Z]$/i';
$letras = "TRWAGMYFPDXBNJZSQVHLCKE";
if (preg_match($nifRegEx, $nif)) return ($letras[(substr($nif, 0, 8) % 23)] == $nif[8]);
else if (preg_match($nieRegEx, $nif)) {
if ($nif[0] == "X") $nif[0] = "0";
else if ($nif[0] == "Y") $nif[0] = "1";
else if ($nif[0] == "Z") $nif[0] = "2";
return ($letras[(substr($nif, 0, 8) % 23)] == $nif[8]);
}
else return false;
}
Validación de un CIF
Para finalizar, hemos incluido una función para comprobar si un código de identificación fiscal (CIF) es válido. De todas las funciones de validación incluidas en esta entrada, ésta es sin duda la más compleja, debido a la estructura de este campo. En la Wikipedia se puede encontrar más información sobre la estructura del CIF.
function cif_valido($cif) {
$cif = strtoupper($cif);
$cifRegEx1 = '/^[ABEH][0-9]{8}$/i';
$cifRegEx2 = '/^[KPQS][0-9]{7}[A-J]$/i';
$cifRegEx3 = '/^[CDFGJLMNRUVW][0-9]{7}[0-9A-J]$/i';
if (preg_match($cifRegEx1, $cif) || preg_match($cifRegEx2, $cif) || preg_match($cifRegEx3, $cif)) {
$control = $cif[strlen($cif) - 1];
$suma_A = 0;
$suma_B = 0;
for ($i = 1; $i < 8; $i++) {
if ($i % 2 == 0) $suma_A += intval($cif[$i]);
else {
$t = (intval($cif[$i]) * 2);
$p = 0;
for ($j = 0; $j < strlen($t); $j++) {
$p += substr($t, $j, 1);
}
$suma_B += $p;
}
}
$suma_C = (intval($suma_A + $suma_B)) . "";
$suma_D = (10 - intval($suma_C[strlen($suma_C) - 1])) % 10;
$letras = "JABCDEFGHI";
if ($control >= "0" && $control <= "9") return ($control == $suma_D);
else return (strtoupper($control) == $letras[$suma_D]);
}
else return false;
}
Todas las expresiones regulares anteriores están escritas en PHP. Si en tu sitio web realizas una doble verificación, tanto desde el lado del cliente (con JavaScript), como del lado del servidor (con PHP); es posible que te interese convertir estas funciones y expresiones regulares a JavaScript. Se trata de una tarea sencilla y puedes encontrar información sobre cómo hacerlo en Internet.
No obstante, aquí dejo una función de ejemplo para la validación de una dirección de correo electrónico con JavaScript:
function email_valido(email) {
email = email.toLowerCase();
var emailRegEx1 = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/i;
var emailRegEx2 = /^.+@.+\.[a-z]{2,4}$/i;
return (emailRegEx1.test(email) && emailRegEx2.test(email));
}
Espero que te sea de gran utilidad. Si te apetece dar tu opinión, puedes utilizar el sistema de comentarios que acabamos de incorporar al blog.
Si te ha gustado esta entrada y quieres apoyarme, puedes invitarme a un café:
5 comentarios
1
Álvaro
25 de septiembre de 2015 a las 12:22 h.25-sep-2015
Hola, me gustaría saber si podrías pasarme los métodos cif_vaido y nif_valido a JavaScript, ya que yo lo he intentado y Suma_B en php me da como resultado 2 y en JavaScript 0, es decir, que algo no está haciendo bien.
Lo he estado probando con el CIF P0200100F y A58818501.
2
VoidWyrm
25 de septiembre de 2015 a las 12:43 h.25-sep-2015
Aquí tienes @Álvaro:
function cif_valido(cif) {
cif = cif.toUpperCase();
var cifRegEx1 = /^[ABEH][0-9]{8}$/i;
var cifRegEx2 = /^[KPQS][0-9]{7}[A-J]$/i;
var cifRegEx3 = /^[CDFGJLMNRUVW][0-9]{7}[0-9A-J]$/i;
if (cifRegEx1.test(cif) || cifRegEx2.test(cif) || cifRegEx3.test(cif)) {
var control = cif.charAt(cif.length - 1);
var suma_A = 0;
var suma_B = 0;
for (var i = 1; i < 8; i++) {
if (i % 2 == 0) suma_A += parseInt(cif.charAt(i));
else {
var t = (cif.charAt(i) * 2) + "";
var p = 0;
for (var j = 0; j < t.length; j++) {
p += parseInt(t.charAt(j));
}
suma_B += p;
}
}
var suma_C = (suma_A + suma_B) + "";
var suma_D = (10 - parseInt(suma_C.charAt(suma_C.length - 1))) % 10;
var letras = "JABCDEFGHI";
if (control >= "0" && control <= "9") return (control == suma_D);
else return (control == letras.charAt(suma_D));
}
else return false;
}
console.log(cif_valido("P0200100F"));
console.log(cif_valido("A58818501"));
3
Álvaro
25 de septiembre de 2015 a las 13:28 h.25-sep-2015
@Antonio: Muchísimas gracias. Ahora me va perfecto.
4
Julia
3 de diciembre de 2015 a las 12:49 h.3-dic-2015
La función que valida el NIE no es correcta.
He hecho estos cambios para que funcione correctamente
function nif_valido($nif) {
$nif = strtoupper($nif);
$nifRegEx = '/^[0-9]{8}[A-Z]$/i';
$nieRegEx = '/^[KLMXYZ][0-9]{7}[A-Z]$/i';
$letras = "TRWAGMYFPDXBNJZSQVHLCKE";
if (preg_match($nifRegEx, $nif)) return ($letras[(substr($nif, 0, 8) % 23)] == $nif[8]);
else if (preg_match($nieRegEx, $nif))
{/**
Los NIE's de extranjeros residentes en España tienen una letra (X, Y, Z), 7 números y dígito de control.
Para el cálculo del dígito de control se sustituye:
X =0
Y =1
Z = 2
y se aplica el mismo algoritmo que para el NIF.*/
$r = str_replace(array('X', 'Y', 'Z'), array(0, 1, 2), $nif);
//echo "letra:". $letras[(substr($r, 0, 8) % 23)]."y nif[8]=".$nif[8]."";
return ($letras[(substr($r, 0, 8) % 23)] == $nif[8]);
}
else return false;
}
5
VoidWyrm
3 de diciembre de 2015 a las 17:59 h.3-dic-2015
@Julia: Pues tienes razón. No sé de donde saqué en su momento esa información, pero está claro que la función no validaba correctamente los NIE.
Ya está corregida la función del NIF/NIE.
Muchas gracias Julia.
Deja tu comentario
Puedes utilizar el siguiente formulario para aportar tu opinión o contestar a otras personas. Por favor, escribe con educación y respeto hacia los demás y no olvides revisar la ortografía. Si tu comentario es muy extenso, puedes separar el texto en varios párrafos.