2011-10-04 58 views
30

Esto no es un gran problema para mí (por lo que yo sé), es más de algo que me interesa. Pero, ¿cuál es la principal diferencia, en su caso, de usar is_numeric sobre preg_match (o viceversa) para validar los valores de entrada del usuario.PHP is_numeric o preg_match 0-9 validación

Ejemplo uno:

<?php 
    $id = $_GET['id']; 
    if (!preg_match('/^[0-9]*$/', $id)) { 
     // Error 
    } else { 
     // Continue 
    } 
?> 

Ejemplo dos:

<?php 
    $id = $_GET['id']; 
    if (!is_numeric($id)) { 
     // Error 
    } else { 
     // Continue 
    } 
?> 

Asumo tanto hacen exactamente lo mismo pero ¿hay diferencias específicas que podrían causar problemas más adelante de alguna manera? ¿Hay una "mejor manera" o algo que no veo que los haga diferentes?

Respuesta

49

is_numeric() prueba si el valor es un número. Sin embargo, no necesariamente tiene que ser un número entero: podría ser un número decimal o un número en notación científica.

El ejemplo preg_match() que ha dado solo comprueba que un valor contiene los dígitos cero a nueve; cualquier número de ellos, y en cualquier secuencia.

Tenga en cuenta que la expresión regular que ha dado también no es un comprobador de enteros perfecto, de la forma en que lo ha escrito.No permite negativos sí permite una cadena de longitud cero (es decir, sin ningún dígito, que presumiblemente no debería ser válida?), y permite que el número tenga cualquier número de ceros a la izquierda, lo que de nuevo puede no ser el deseado.

[EDIT]

De acuerdo con su comentario, una mejor expresión regular podría tener este aspecto:

/^[1-9][0-9]*$/ 

Fuerza al primer dígito solamente estar entre 1 y 9, por lo que no puede tener ceros a la izquierda También lo obliga a tener al menos un dígito de longitud, por lo que resuelve el problema de cadena de longitud cero.

No le preocupan los aspectos negativos, por lo que no es un problema.

Es posible que desee restringir el número de dígitos, porque tal como están las cosas, permitirá que las cadenas que son demasiado grandes se almacenen como enteros. Para limitar este, que iba a cambiar la estrella en una restricción de longitud de este modo:

/^[1-9][0-9]{0,15}$/ 

Esto permitiría a la cadena a estar entre 1 y 16 dígitos de longitud (es decir, el primer dígito se añaden otros 0-15 dígitos). Siéntase libre de ajustar los números en las llaves para satisfacer sus propias necesidades. Si desea una cadena de longitud fija, solo necesita especificar un número entre las llaves.

Espero que ayude.

+0

Entonces, con la Regex ¿cómo se puede rectificar el problema de los ceros a la izquierda, etc.? Esto podría causarme problemas después de todo, ya que este es el método que he estado usando. Si solo quiero validar que era un número entero (4,8,15,16,23,42,108 etc.), sin ceros a la izquierda, sin puntos decimales, sin negativos, ¿cómo se lograría esto? – Joe

+0

@JoeMottershaw - Editaré la respuesta para agregar más información ... – Spudley

+0

Gracias, Spudley, esa es una explicación muy clara: definitivamente entiendo mejor sus diferencias. ¡Parece que volveré y ajustaré un poco mi código! :) – Joe

1

Si eres única comprobar si se trata de un número, is_numeric() es mucho mucho mejor aquí. Es más legible y un poco más rápido que regex.

El problema con su expresión regular aquí es que no permitirá valores decimales, por lo que esencialmente acaba de escribir is_int() en expresiones regulares. Las expresiones regulares solo deben usarse cuando hay un formato de datos no estándar en su entrada; PHP tiene muchas funciones de validación integradas, incluso una email validator without regex.

+0

No creo que 'is_int()' hace lo que usted cree - que en realidad comprueba el tipo de variable que está siendo controlada; no es un validador de cadenas – Spudley

4

is_numeric aceptará "-0.5e + 12" como identificación válida.

5

No es exactamente lo mismo.

De la documentación de PHP de is_numeric:

'42' is numeric 
'1337' is numeric 
'1e4' is numeric 
'not numeric' is NOT numeric 
'Array' is NOT numeric 
'9.1' is numeric 

Con su expresión regular sólo se comprueba para los valores numéricos 'básicos'.

También is_numeric() debería ser más rápido.

+0

Así que usar 'is_numeric' para comprobar contra una entrada de entrada en un foro que tienen identificadores únicos asignados por' auto_increment', puede causar problemas ya que la base de datos solo tiene números enteros, no decimales, símbolos, etc. – Joe

+0

@Joe Mottershaw: si eso es el caso en el que usaría 'is_int()' – PeeHaa

+0

@JoeMottershaw: o quizás sería mejor que lo escriba en un int: '$ id = (int) $ _REQUEST ['id'];' – PeeHaa

7

is_numeric() permite cualquier forma de número. por lo 1, 3.14159265, 2.71828e10 son todos "numérico", mientras que su expresión regular reduce al equivalente de is_int()

+0

No estoy seguro de cómo funcionó ' 11. Pero ahora 'is_int' y' is_integer' en realidad devuelven falso para cualquier cadena dada – cvsguimaraes

3

is_numeric cheques más:

Encuentra si la variable dada es numérica. Las cadenas numéricas consisten en de signo opcional, cualquier número de dígitos, parte decimal opcional y parte exponencial opcional. Por lo tanto + 0123.45e6 es un valor numérico válido. Se permite la notación hexadecimal (0xFF) pero solo sin signo, parte decimal y exponencial.

10

De acuerdo con http://www.php.net/manual/en/function.is-numeric.php, is_numeric alows algo así como "+ 0123.45e6" o "0xFF". Creo que esto no es lo que esperas.

preg_match puede ser lenta, y se puede tener algo así como 0000 o 0051.

Yo prefiero usar ctype_digit (sólo funciona con cadenas, que está bien con $ _GET).

<?php 
    $id = $_GET['id']; 
    if (ctype_digit($id)) { 
     echo 'ok'; 
    } else { 
     echo 'nok'; 
    } 
?> 
+0

Así que 'ctype_digit' solo comprueba si hay números redondeados, ¿qué tal si es un número positivo o negativo? ¿Cómo funciona con eso? – Joe

+0

Funciona solo con números positivos, creo que puede ser útil para una identificación (no tengo Ids negativos en mi código): var_dump (ctype_digit ('- 5')); // devuelve falso –

5

cheques is_numeric si se trata de cualquier tipo de número, mientras que los cheques de expresiones regulares si se trata de un número entero, posiblemente con 0s principales. Para una identificación, almacenada como un entero, es bastante probable que no tengamos los 0 principales. Tras la respuesta de Spudley, podemos hacer:

/^[1-9][0-9]*$/ 

Sin embargo, como señala Spudley, la cadena resultante puede ser demasiado grande para ser almacenado como un valor entero de 32 bits o 64 bits. El valor máximo de un entero de 32 bits con signo es 2.147.483.647 (10 dígitos), y el valor máximo de un entero de 64 bits con signo es de 9,223,372,036,854,775,807 (19 dígitos). Sin embargo, muchos enteros de 10 y 19 dígitos son más grandes que los enteros máximos de 32 bits y 64 bits, respectivamente. Una solución simple expresión regular de sólo sería:

/^[1-9][0-9]{0-8}$/ 

o

/^[1-9][0-9]{0-17}$/ 

respectivamente, pero estas "soluciones" infelizmente restringir cada a 9 y 19 números enteros dígitos; difícilmente un resultado satisfactorio. Una mejor solución podría ser algo como:

$expr = '/^[1-9][0-9]*$/'; 
if (preg_match($expr, $id) && filter_var($id, FILTER_VALIDATE_INT)) { 
    echo 'ok'; 
} else { 
    echo 'nok'; 
} 
1

función de PHP is_numeric permite la flota, así como enteros. Al mismo tiempo, la función is_int es demasiado estricta si desea validar los datos del formulario (solo cadenas). Por lo tanto, generalmente es mejor usar expresiones regulares para esto.

Estrictamente hablando, enteros son números enteros positivos y negativos, y también incluyendo cero. Aquí es una expresión regular para esto:?

/^ $ 0 |^[-] [1-9] [0-9] * $/

O, si desea permitir ceros a la izquierda:

/^ [-] [0] | [1-9] [0-9] $/

Tenga en cuenta que esto permitirá valores como -0000? , que no causa problemas en PHP, h sin embargo. (MySQL también arrojará valores como 0.)

También puede limitar la longitud de su número entero por consideraciones de 32/64-bit PHP platform features y/o compatibilidad de bases de datos. Por ejemplo, para limitar la longitud de su número entero a 9 dígitos (excluyendo el signo opcional), puede usar:

/^ 0 $ |^[-]? [1-9] [0-9 ] {0,8} $/

0

Mientras tanto, todos los valores anteriormente sólo se restringen los valores a un entero, así que utilizo

/^[1-9][0-9\.]{0,15}$/ 

para permitir valores de coma flotante también.

0

Usted puede utilizar este código para la validación de número:

if (!preg_match("/^[0-9]+$/i", $phone)) { 
     $errorMSG = 'Invalid Number!'; 
     $error = 1; 
    }