Я работаю над пакетом валидатора данных для PHP (в основном как упражнение в некоторых новых дополнениях в 5.3, таких как пространства имен). Я планирую иметь основной класс валидатора, который использует классы плагинов для фактической проверки.
Первый плагин проверки, который я строю, просто для целых чисел. Источник ниже:
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); } }
Я использую следующие тесты вышеуказанного класса:
$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");
Из приведенных выше тестовых примеров я получаю следующие результаты:
bool (true) int (3735928559) 3735928559
bool (true) int (3735928559) 3735928559
bool (true) int (511) 511
bool (true) int (777) 777
Как вы можете видеть, я столкнулся с проблемой со строкой, которая кодирует восьмеричное число. Он должен оцениваться до 511 (0777 в базе 10), но я фактически получаю 777 вместо этого.
Поскольку однажды я могу использовать этот класс для проверки форм, и поскольку формы всегда рассматриваются как массивы строк PHP, вы можете видеть, что обработка восьмеричных чисел, которые являются строками с этим плагином, является проблематичной.
Я пробовал различные подходы к целочисленной проверке (с помощью is_int всегда возвращает false для строк, умножая на 1, а is_numeric не будет захватывать float, typecasting и intval – создает нежелательный результат при работе с восьмеричными числами). Есть ли другой подход, который я мог бы использовать, который будет работать для базы 10 (десятичный), базы 16 (шестнадцатеричный) и базы 8 (восьмеричный)?
intval
имеет необязательный аргумент $base
:
intval('0777', 8); // 511 intval('0777', 10); // 777 intval('0777'); // 777 intval(0777); // 511
Поэтому вы можете сделать что-то вроде этого:
$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);
Сначала вам нужно определить, как восьмеричное число представлено в строке. Потому что некоторые люди склонны говорить, что строка типа "0777"
является десятичным значением 777
.
Итак, как ваш класс должен знать, что думал пользователь при выполнении ввода, который вы хотели бы проверить (или более правильно преобразовать в целочисленное значение).
Насколько вам интересно, чтобы имитировать то, как сам PHP решает значение «как PHP», вы можете имитировать с помощью eval ( Demo ):
<?php $value = '0777'; $value = eval("return $value;"); var_dump($value);
Однако это не решает основной проблемы дизайна. У вас должен быть DecimalInteger
или HexadecimalInteger
или OctalInteger
для вашей линейки ваших классов песочницы.