Мне нужна простая php-библиотека, которую можно легко использовать для передачи правил и имен полей, а затем проверка может быть легко выполнена. Также должен быть простой способ получить ошибки.
Какие-либо предложения?
Я написал свой собственный класс, объединив некоторые регулярные выражения, которые я собирал на протяжении многих лет с помощью функций санации и фильтрации PHP.
<? /** * Pork Formvalidator. validates fields by regexes and can sanatize them. Uses PHP filter_var built-in functions and extra regexes * @package pork */ /** * Pork.FormValidator * Validates arrays or properties by setting up simple arrays * * @package pork * @author SchizoDuckie * @copyright SchizoDuckie 2009 * @version 1.0 * @access public */ class FormValidator { public static $regexes = Array( 'date' => "^[0-9]{4}[-/][0-9]{1,2}[-/][0-9]{1,2}\$", 'amount' => "^[-]?[0-9]+\$", 'number' => "^[-]?[0-9,]+\$", 'alfanum' => "^[0-9a-zA-Z ,.-_\\s\?\!]+\$", 'not_empty' => "[a-z0-9A-Z]+", 'words' => "^[A-Za-z]+[A-Za-z \\s]*\$", 'phone' => "^[0-9]{10,11}\$", 'zipcode' => "^[1-9][0-9]{3}[a-zA-Z]{2}\$", 'plate' => "^([0-9a-zA-Z]{2}[-]){2}[0-9a-zA-Z]{2}\$", 'price' => "^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?\$", '2digitopt' => "^\d+(\,\d{2})?\$", '2digitforce' => "^\d+\,\d\d\$", 'anything' => "^[\d\D]{1,}\$" ); private $validations, $sanatations, $mandatories, $errors, $corrects, $fields; public function __construct($validations=array(), $mandatories = array(), $sanatations = array()) { $this->validations = $validations; $this->sanatations = $sanatations; $this->mandatories = $mandatories; $this->errors = array(); $this->corrects = array(); } /** * Validates an array of items (if needed) and returns true or false * */ public function validate($items) { $this->fields = $items; $havefailures = false; foreach($items as $key=>$val) { if((strlen($val) == 0 || array_search($key, $this->validations) === false) && array_search($key, $this->mandatories) === false) { $this->corrects[] = $key; continue; } $result = self::validateItem($val, $this->validations[$key]); if($result === false) { $havefailures = true; $this->addError($key, $this->validations[$key]); } else { $this->corrects[] = $key; } } return(!$havefailures); } /** * * Adds unvalidated class to thos elements that are not validated. Removes them from classes that are. */ public function getScript() { if(!empty($this->errors)) { $errors = array(); foreach($this->errors as $key=>$val) { $errors[] = "'INPUT[name={$key}]'"; } $output = '$$('.implode(',', $errors).').addClass("unvalidated");'; $output .= "alert('there are errors in the form');"; // or your nice validation here } if(!empty($this->corrects)) { $corrects = array(); foreach($this->corrects as $key) { $corrects[] = "'INPUT[name={$key}]'"; } $output .= '$$('.implode(',', $corrects).').removeClass("unvalidated");'; } $output = "<script type='text/javascript'>{$output} </script>"; return($output); } /** * * Sanatizes an array of items according to the $this->sanatations * sanatations will be standard of type string, but can also be specified. * For ease of use, this syntax is accepted: * $sanatations = array('fieldname', 'otherfieldname'=>'float'); */ public function sanatize($items) { foreach($items as $key=>$val) { if(array_search($key, $this->sanatations) === false && !array_key_exists($key, $this->sanatations)) continue; $items[$key] = self::sanatizeItem($val, $this->validations[$key]); } return($items); } /** * * Adds an error to the errors array. */ private function addError($field, $type='string') { $this->errors[$field] = $type; } /** * * Sanatize a single var according to $type. * Allows for static calling to allow simple sanatization */ public static function sanatizeItem($var, $type) { $flags = NULL; switch($type) { case 'url': $filter = FILTER_SANITIZE_URL; break; case 'int': $filter = FILTER_SANITIZE_NUMBER_INT; break; case 'float': $filter = FILTER_SANITIZE_NUMBER_FLOAT; $flags = FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND; break; case 'email': $var = substr($var, 0, 254); $filter = FILTER_SANITIZE_EMAIL; break; case 'string': default: $filter = FILTER_SANITIZE_STRING; $flags = FILTER_FLAG_NO_ENCODE_QUOTES; break; } $output = filter_var($var, $filter, $flags); return($output); } /** * * Validates a single var according to $type. * Allows for static calling to allow simple validation. * */ public static function validateItem($var, $type) { if(array_key_exists($type, self::$regexes)) { $returnval = filter_var($var, FILTER_VALIDATE_REGEXP, array("options"=> array("regexp"=>'!'.self::$regexes[$type].'!i'))) !== false; return($returnval); } $filter = false; switch($type) { case 'email': $var = substr($var, 0, 254); $filter = FILTER_VALIDATE_EMAIL; break; case 'int': $filter = FILTER_VALIDATE_INT; break; case 'boolean': $filter = FILTER_VALIDATE_BOOLEAN; break; case 'ip': $filter = FILTER_VALIDATE_IP; break; case 'url': $filter = FILTER_VALIDATE_URL; break; } return ($filter === false) ? false : filter_var($var, $filter) !== false ? true : false; } }
Теперь для этого требуется mootools для некоторого javascript, который вы видите здесь, но вы можете легко изменить его на свою любимую фреймворк javascript. Все, что он делает, – это найти элемент и добавить к нему «неутвержденный» класс CSS.
Использование так же просто, как я всегда хотел:
Пример:
$validations = array( 'name' => 'anything', 'email' => 'email', 'alias' => 'anything', 'pwd'=>'anything', 'gsm' => 'phone', 'birthdate' => 'date'); $required = array('name', 'email', 'alias', 'pwd'); $sanatize = array('alias'); $validator = new FormValidator($validations, $required, $sanatize); if($validator->validate($_POST)) { $_POST = $validator->sanatize($_POST); // now do your saving, $_POST has been sanatized. die($validator->getScript()."<script type='text/javascript'>alert('saved changes');</script>"); } else { die($validator->getScript()); }
Чтобы проверить только один элемент:
$validated = new FormValidator()->validate('blah@bla.', 'email');
Санация только одного элемента:
$sanatized = new FormValidator()->sanatize('<b>blah</b>', 'string');
Самое крутое в этом классе – это то, что вы можете отправить свою форму с помощью ajax или iframe target и выполнить полученный скрипт. Не нужно обновлять страницу или повторно отправлять те же данные формы обратно в браузер 🙂 Кроме того, если сценарий нуждается в изменении, нет сложной переопределенной структуры для анализа, просто измените ее так, как вы хотите 🙂
О да, не стесняйтесь использовать это где угодно. Нет лицензий
Ответ от SchizoDuckie выше был потрясающим. Я использовал его код в проекте, над которым я работаю, с разрешения автора. Одна из проблем, которые я использовал с этим кодом, заключалась в том, что если обязательное поле не было отправлено, оно не зарегистрировало бы ошибку. Я изменил код, чтобы охватить этот сценарий. Я также удалил код для генерации HTML и javascript, так как мой проект требует разделения UI от логики на шаблон MVC. Измененный код просто возвращает результат, закодированный JSON. Я перепрограммирую измененный код здесь, если он будет полезен другим.
<? /** * Pork Formvalidator. validates fields by regexes and can sanatize them. Uses PHP filter_var built-in functions and extra regexes * @package pork */ /** * Pork.FormValidator * Validates arrays or properties by setting up simple arrays * * @package pork * @author SchizoDuckie * @copyright SchizoDuckie 2009 * @version 1.0 * @access public */ class FormValidator { public static $regexes = Array( 'date' => "^[0-9]{4}[-/][0-9]{1,2}[-/][0-9]{1,2}\$", 'amount' => "^[-]?[0-9]+\$", 'number' => "^[-]?[0-9,]+\$", 'alfanum' => "^[0-9a-zA-Z ,.-_\\s\?\!]+\$", 'not_empty' => "[a-z0-9A-Z]+", 'words' => "^[A-Za-z]+[A-Za-z \\s]*\$", 'phone' => "^[0-9]{10,11}\$", 'zipcode' => "^[1-9][0-9]{3}[a-zA-Z]{2}\$", 'plate' => "^([0-9a-zA-Z]{2}[-]){2}[0-9a-zA-Z]{2}\$", 'price' => "^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?\$", '2digitopt' => "^\d+(\,\d{2})?\$", '2digitforce' => "^\d+\,\d\d\$", 'anything' => "^[\d\D]{1,}\$", 'username' => "^[\w]{3,32}\$" ); private $validations, $sanatations, $mandatories, $equal, $errors, $corrects, $fields; public function __construct($validations=array(), $mandatories = array(), $sanatations = array(), $equal=array()) { $this->validations = $validations; $this->sanatations = $sanatations; $this->mandatories = $mandatories; $this->equal = $equal; $this->errors = array(); $this->corrects = array(); } /** * Validates an array of items (if needed) and returns true or false * * JP modofied this function so that it checks fields even if they are not submitted. * for example the original code did not check for a mandatory field if it was not submitted. * Also the types of non mandatory fields were not checked. */ public function validate($items) { $this->fields = $items; $havefailures = false; //Check for mandatories foreach($this->mandatories as $key=>$val) { if(!array_key_exists($val,$items)) { $havefailures = true; $this->addError($val); } } //Check for equal fields foreach($this->equal as $key=>$val) { //check that the equals field exists if(!array_key_exists($key,$items)) { $havefailures = true; $this->addError($val); } //check that the field it's supposed to equal exists if(!array_key_exists($val,$items)) { $havefailures = true; $this->addError($val); } //Check that the two fields are equal if($items[$key] != $items[$val]) { $havefailures = true; $this->addError($key); } } foreach($this->validations as $key=>$val) { //An empty value or one that is not in the list of validations or one that is not in our list of mandatories if(!array_key_exists($key,$items)) { $this->addError($key, $val); continue; } $result = self::validateItem($items[$key], $val); if($result === false) { $havefailures = true; $this->addError($key, $val); } else { $this->corrects[] = $key; } } return(!$havefailures); } /* JP * Returns a JSON encoded array containing the names of fields with errors and those without. */ public function getJSON() { $errors = array(); $correct = array(); if(!empty($this->errors)) { foreach($this->errors as $key=>$val) { $errors[$key] = $val; } } if(!empty($this->corrects)) { foreach($this->corrects as $key=>$val) { $correct[$key] = $val; } } $output = array('errors' => $errors, 'correct' => $correct); return json_encode($output); } /** * * Sanatizes an array of items according to the $this->sanatations * sanatations will be standard of type string, but can also be specified. * For ease of use, this syntax is accepted: * $sanatations = array('fieldname', 'otherfieldname'=>'float'); */ public function sanatize($items) { foreach($items as $key=>$val) { if(array_search($key, $this->sanatations) === false && !array_key_exists($key, $this->sanatations)) continue; $items[$key] = self::sanatizeItem($val, $this->validations[$key]); } return($items); } /** * * Adds an error to the errors array. */ private function addError($field, $type='string') { $this->errors[$field] = $type; } /** * * Sanatize a single var according to $type. * Allows for static calling to allow simple sanatization */ public static function sanatizeItem($var, $type) { $flags = NULL; switch($type) { case 'url': $filter = FILTER_SANITIZE_URL; break; case 'int': $filter = FILTER_SANITIZE_NUMBER_INT; break; case 'float': $filter = FILTER_SANITIZE_NUMBER_FLOAT; $flags = FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND; break; case 'email': $var = substr($var, 0, 254); $filter = FILTER_SANITIZE_EMAIL; break; case 'string': default: $filter = FILTER_SANITIZE_STRING; $flags = FILTER_FLAG_NO_ENCODE_QUOTES; break; } $output = filter_var($var, $filter, $flags); return($output); } /** * * Validates a single var according to $type. * Allows for static calling to allow simple validation. * */ public static function validateItem($var, $type) { if(array_key_exists($type, self::$regexes)) { $returnval = filter_var($var, FILTER_VALIDATE_REGEXP, array("options"=> array("regexp"=>'!'.self::$regexes[$type].'!i'))) !== false; return($returnval); } $filter = false; switch($type) { case 'email': $var = substr($var, 0, 254); $filter = FILTER_VALIDATE_EMAIL; break; case 'int': $filter = FILTER_VALIDATE_INT; break; case 'boolean': $filter = FILTER_VALIDATE_BOOLEAN; break; case 'ip': $filter = FILTER_VALIDATE_IP; break; case 'url': $filter = FILTER_VALIDATE_URL; break; } return ($filter === false) ? false : filter_var($var, $filter) !== false ? true : false; } } ?>
Если вы хотите запрограммировать некоторые по своему усмотрению, у вас есть PHP 5.2.0 или выше. Затем вы можете просмотреть функции фильтра.
Существует также эта библиотека на github: https://github.com/blackbelt/php-validation
Zend Forms, которые могут использоваться без всей структуры Zend
Существует один, включенный в рамки Code Igniter, посмотрите здесь
Я рекомендую начать использовать одну из фреймворков PHP;)
У вас есть часть структуры symfony с именем symfony , которая может использоваться отдельно от всей структуры.
Взгляните на документацию по инфраструктуре .
Этот класс проверки phpro.org выглядит очень хорошо для простой проверки данных:
http://www.phpro.org/classes/Validation-Class.html
Он поддерживает такие правила, как длина и т. Д.