¿En qué podemos ayudarte?
Validar las entradas numéricas puede representar un quebradero de cabeza porque hay numerosos formatos de entrada válidos. En un formulario interactivo podemos forzar un formato de entrada, pero perdemos en usabilidad al restringir la libertad del usuario. Sin embargo, lo tendremos más complicado si nos llega un gran volumen de datos desde una fuente externa sobre la que no tenemos control.
En mi caso, al actualizar el catálogo de la tienda, encontré con que los precios, medidas y otros numéricos importantes datos me llegaban en formatos diferentes, Es algo habitual cuando integras diferentes sistemas y/o incorporas información de diferentes fuentes, no solo tendremos que lidiar con la presentación de los números, también en muchos casos con las unidades y otros textos complementarios.
Por ese motivo os presento una pequeña función que nos facilitará la tarea de validar entradas numéricas para cualquier formato de entrada
¿Por qué validar las entradas numéricas?
En PHP, y prácticamente en todos los lenguajes de programación, los valores numéricos se representan internamente mediante un signo opcional, uno o más dígitos, con el punto (.) como separador decimal y opcionalmente un exponente. El exponente es una (e) o (E) seguida de uno o más dígitos con signo.
Sin embargo en el mundo real también usamos separadores de miles. En muchos casos la coma (,) se intercambia con el punto. Frecuentemente, nos encontraremos con que los usuarios darán formato a los números y también muchos sistemas de información aplican las convenciones locales al visualizar números. Por tanto, en más de una ocasión nos encontraremos con que formato en que nos llega la información no se corresponde con formato interno.
Si únicamente visualizaremos la información, podemos dejarlo así. Pero si tenemos que operar con los números recibidos, no podemos confiar ciegamente en la conversión implícita del lenguaje que usamos o nos llevaremos más de una sorpresa desagradable.
En el mejor de los casos tendremos un error y lo corregiremos, pero probablemente tendremos un resultado incorrecto sobre el que no sabremos nada. Hasta que nos llueven pedidos de un producto que estamos "vendiendo" a precios ridículos. Entonces es demasiado tarde, el mal está hecho
Validador universal de entradas numéricas
A continuación os muestro una función que soluciona este problema
function rjc_tofloat($num) {
$num=trim($num);
if ($num==='') {return 0;}
else {
do {
$signo=$num[0]; $num=substr($num, 1);
$Ok=strpos("-+.0123456789",$signo);
}
while($num!=='' && $Ok===false);
if ($signo==='-' || $signo==='+') {$resulta=$num;}
else if ($signo==='.') {$resulta='0.'.$num; $signo='';}
else {$resulta=$signo.$num; $signo='';}
if ($resulta==='') {return 0;}
$num=$resulta;
$dotPos = strrpos($num, '.');
$commaPos = strrpos($num, ',');
$sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos :
((($commaPos > $dotPos) && $commaPos) ? $commaPos : false);
if (!$sep) {return floatval($signo.preg_replace("/[^0-9]/", "", $num));}
return floatval($signo.
preg_replace("/[^0-9]/", "", substr($num, 0, $sep)) . '.' .
preg_replace("/[^0-9]/", "", substr($num, $sep+1, strlen($num)))
);
}
}
La lógica es simple, primero comprobamos si hay separadores. Si los hay asumimos que el que está más a la derecha es el separador decimal. Eliminamos los caracteres no válidos y devolvemos un número con el punto como separador decimal.
Obviamente, no estamos ante un validador universal, por ejemplo no se tiene en cuenta la notación científica. Pero cubre perfectamente mis casos de uso, en los que espero un número en notación decimal y como mucho un texto adicional: como puede ser la moneda si es un precio, o la unidad de medida.
Es una función que encuentro lo suficientemente útil para estar en el functions.php de nuestro tema hijo o en un plugin si este nos parece una mejor opción. En cualquier caso nos facilitará la tarea de validar las entradas numéricas en nuestra web.
La idea del algoritmo puede ser implementada fácilmente en otros lenguajes, como por ejemplo en Javascript para validar en tiempo real los números introducidos por un usuario. Podéis comprobar su funcionamiento en el formulario.
Número en cualquier formato
Número normalizado
Conclusión
Hemos visto un algoritmo muy simple de implementar que nos permite validar las entradas numéricas y normalizar su formato. Al mismo tiempo se le permite al usuario usar la notación a la que está acostumbrado. No corrige números mal escritos, su objetivo es el contrario, admitir la mayor cantidad de notaciones correctas y pasarlas a nuestro formato normalizado.
Espero que la función propuesta os sea útil en vuestro día a día y modificarla para cubrir otros casos no es complicado. En breve os presentaré una función similar para aliviar el otro gran dolor de cabeza de muchos de nosotros: la validación de fechas.
Si te has encontrado con este problema y lo has solucionado de otra forma, participa y cuéntalo en los comentarios. Tu aportación es bienvenida