Encasting de enteros confiables

Estoy trabajando en un paquete de validación de datos para PHP (principalmente como un ejercicio en algunas de las nuevas adiciones en 5.3 como espacios de nombres). Estoy planeando tener una clase de validador principal que use clases de complemento para hacer la validación real.

El primer complemento de validación que estoy construyendo es solo uno simple para enteros. La fuente está abajo:

namespace validator\validatorplugins; class Integer implements ValidatorPlugin { private $field = NULL; public function cast () { return ($this -> field = (int) ($this -> field * 1)); } public function isValid () { if (!$isValid = is_int ($this -> field * 1)) { $this -> field = NULL; } return ($isValid); } public function __construct ($field) { $this -> field = $field; } public function __toString() { return ((string) $this -> field); } } 

Estoy usando las siguientes pruebas de la clase anterior:

 $a = new Integer (0xDEADBEEF); var_dump ($a -> isValid ()); var_dump ($a -> cast ()); echo ($a . "\n\n"); $b = new Integer ('0xDEADBEEF'); var_dump ($b -> isValid ()); var_dump ($b -> cast ()); echo ($b . "\n\n"); $c = new Integer (0777); var_dump ($c -> isValid ()); var_dump ($c -> cast ()); echo ($c . "\n\n"); $d = new Integer ('0777'); var_dump ($d -> isValid ()); var_dump ($d -> cast ()); echo ($d . "\n\n"); 

De los casos de prueba anteriores, obtengo los siguientes resultados:

bool (verdadero) int (3735928559) 3735928559

bool (verdadero) int (3735928559) 3735928559

bool (verdadero) int (511) 511

bool (verdadero) int (777) 777

Como puede ver, me encontré con un problema con una cadena que codifica un número octal. Debería evaluar a 511 (0777 en base 10), pero en realidad estoy obteniendo 777.

Como es posible que algún día quiera utilizar esta clase para validar formularios, y como los formularios siempre se tratan como matrices de cadenas mediante PHP, puede ver que el procesamiento de números octales que resultan ser cadenas con este complemento es problemático.

He intentado varios enfoques para la validación de enteros (usar is_int siempre devuelve false para cadenas, multiplicar por 1 e is_numeric no capturará flotantes, encasillamiento y intval producen un resultado no deseado cuando se trata de números octales). ¿Hay algún otro enfoque que pueda usar que funcione para la base 10 (decimal), la base 16 (hex) y la base 8 (octal)?

intval tiene un argumento opcional $base :

 intval('0777', 8); // 511 intval('0777', 10); // 777 intval('0777'); // 777 intval(0777); // 511 

Entonces podrías hacer algo como esto:

 $i = '0777'; $base = 10; if (strtolower(substr($i, 0, 2)) === '0x') $base = 16; else if (substr($i, 0, 1) === '0') $base = 8; intval($i, $base); 

Primero necesita definir cómo se representa un número octal en una cadena. Porque algunas personas tienden a decir que una cadena como "0777" es el valor decimal de 777 .

Entonces, ¿cómo debería saber su clase lo que el usuario pensó al hacer la entrada que le gustaría validar (o más correctamente convertir en un valor entero)?

En lo que a ti respecta, imita cómo PHP resuelve el valor “como PHP”, puedes simular con eval ( Demo ):

  

Sin embargo, esto no resuelve el problema de diseño subyacente. Deberías tener un DecimalInteger o un HexadecimalInteger o un OctalInteger para tu alineación de tus clases de sandbox.