Привет. Пишу свой велосипед т.е. OOP, MVC фреймворк. В процессе решил не писать проверки в моделе Аккаунта, а написать отдельный класс валидации форм (в итоге я его стащил с github =)). Идея заключалась в том, что к полю можно применить несколько методов валидации, допустим: Поле логин обязательно к заполнению. Логин должен состоять только из русскиз букв. Логин должен состоять не менее чем из 3-х символов. То есть чтобы для каждого неверного действия вываливалось по 1-му сообщению, а не пачкой или вообще в одну строчку. Код, который я нарыл рабочий на 100%, но в итоге столкнулся с тем, что не могу с помощью этого класса проверить, скажем email на существовании в БД… В ситуации, когда в базе данных уже есть такой пароль, email или логин нужно показать сообщение, что таковые имеются, но я не доганяю, что нужно делать. Лезть в БД в этом класе нет смысла, потому что это задача модели аккаунта. В этом классе возможно сделать такие проверки? Может подскажите другой класс примерно такой же сложности. В общем буду рад любому дельному совету. Код валидатора PHP: <?php namespace components\libs; class Validator { private $field_name; private $message; private $type_of_rule; private $param; private static $rules = []; private static $fields = []; private static $errors = []; public function __construct($field_name, $message, $type_of_rule, $param) { $this->field_name = $field_name; $this->message = $message; $this->type_of_rule = $type_of_rule; $this->param = $param; } public static function addRule($field_name, $message, $type_of_rule, $param = null) { self::$rules[] = new Validator($field_name, $message, $type_of_rule, $param); } public static function addEntries($fields) { foreach ($fields as $fieldname => $value) { self::$fields[$fieldname] = self::sanitize($value); } } public static function validate() { foreach (self::$rules as $rule) { self::testRule($rule); } } public static function sanitize($text) { $text = trim(strip_tags($text)); if (get_magic_quotes_gpc()) { $text = stripslashes($text); } return $text; } public static function getErrors() { if (count(self::$errors)) { return self::$errors; } return false; } public static function longerThan($value, $min) { if (strlen($value) >= $min) { return true; } return false; } public static function shorterThan($value, $max) { if (strlen($value) <= $max) { return true; } return false; } public static function asEmail($value) { if (filter_var($value, FILTER_VALIDATE_EMAIL)) { return true; } return false; } public static function asPhoneNumber($value) { if (preg_match("/^\(?[0-9]{3}\)? *-? *[0-9]{3} *-? *[0-9]{4}$/", $value)) { return true; } return false; } private static function testRule($rule) { if (isset(self::$errors[$rule->field_name])) { return; } if (isset(self::$fields[$rule->field_name])) { $value = self::$fields[$rule->field_name]; } else { $value = null; } switch ($rule->type_of_rule) { case 'required' : if (empty($value)) { self::$errors[$rule->field_name] = $rule->message; return; } break; case 'minlength' : if (!(self::longerThan($value, $rule->param))) { self::$errors[$rule->field_name] = $rule->message; return; } break; case 'maxlength' : if (!(self::shorterThan($value, $rule->param))) { self::$errors[$rule->field_name] = $rule->message; return; } break; case 'email' : if (!(self::asEmail($value))) { self::$errors[$rule->field_name] = $rule->message; return; } break; case 'phonenumber' : if (!(self::asPhoneNumber($value))) { self::$errors[$rule->field_name] = $rule->message; return; } break; } } } В контролере прописивается всё следующим образом: PHP: public function indexAction() { if (isset($_POST['submit'])){ $name = $_POST['name']; Validator::addRule( 'name', 'Поле name обязательное', 'required'); Validator::addRule( 'name', 'Имя должно состоять не менне чем из 2-х символов', 'minlength', 3); Validator::addEntries($_POST); Validator::validate(); $errors = Validator::getErrors(); } }
Дак у тебя есть проверка на email PHP: public static function asEmail($value) { if (filter_var($value, FILTER_VALIDATE_EMAIL)) { return true; } return false; } Как раз вот в этой строке if (filter_var($value, FILTER_VALIDATE_EMAIL)){} у тебя проверка.
Мне нужна не проверка электронки на правильность, а проверка её существования в БД. То есть чтобы с такой же зарегистрироваться было невозможно. На данный момент я сделал просто: PHP: public function registerAction(){ if(isset($_POST['submit'])){ $model = new Account; $name = $_POST['name']; $email = $_POST['email']; $password = $_POST['password']; $errors = false; if(!$model->checkName($name)){ $errors[] = 'Имя не должно быть короче 2-х символов'; } if(!$model->checkEmail($email)){ $errors[] = 'Неправильный email'; } if(!$model->checkPassword($password)){ $errors[] = 'Пароль не должен быть короче 6-ти символов'; } if($model->checkEmailExists($email)){ $errors[] = 'Такой email уже исспользуется'; } if ($errors == false){ $model->register($name,$email,$password); header("Location: /"); } } var_dump($_POST); $this->set(compact('errors','name','email','password')); } Вот этот кусок кода PHP: if($model->checkEmailExists($email)){ $errors[] = 'Такой email уже исспользуется'; } ищет в таблице users электронку и возвращает её id, а в моделе это выглядит так: PHP: public function checkEmailExists($email) { $params = [ 'email' => $email ]; return $this->db->row('SELECT id FROM users WHERE email = :email', $params); } Нужно написать функцию которая будет получать результат работы метода из модели и в массив getErrors() должно попасть что-то типа "Такой email уже исспользуется" и не пропускать до тех пор пока не будет введён email которого нет в БД. В общем хочется так, но пока что не получается. Не понимаю я как это всё связать. Ведь что-то простое он обрабатывает: правильность введённого того же email или длину логина, сложность пароля и т.п. Вот как проверить существование какой-то записи в БД и выдать ошибку... В общем не знаю как такое написать. По этому и обратился к вам. Помогут любые советы =)
PHP: public function checkEmailExists($email) { $params = [ 'email' => $email ]; return $this->db->row('SELECT id FROM users WHERE email = :email', $params); } этот кусок кода можно заменить на: PHP: public function checkEmailExists($email) { return $this->db->row('SELECT id FROM users WHERE email = :email', $email); } ну а так верно делаешь запрос в бд, проверяешь есть ли там такой email если да сообщаешь, такой email занят другим пользователем.
Да нет =) У меня вот так, не прокатит: PHP: public function checkEmailExists($email) { return $this->db->row('SELECT id FROM users WHERE email = :email', $email); } Ругается. Код БД: PHP: class DB { use Singleton; protected $db; /** * DB constructor. */ protected function __construct(){ $db = require ROOT . '/components/config/config_db.php'; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; $this->db = new PDO($db['dsn'],$db['user'],$db['pass'],$opt); } public function query($sql, $params = []) { $stmt = $this->db->prepare($sql); if (!empty($params)) { foreach ($params as $key => $val) { if (is_int($val)) { $type = PDO::PARAM_INT; } else { $type = PDO::PARAM_STR; } $stmt->bindValue(':'.$key, $val, $type); } } $stmt->execute(); return $stmt; } public function row($sql, $params = []) { $result = $this->query($sql, $params); return $result->fetchAll(); } public function column($sql, $params = []) { $result = $this->query($sql, $params); return $result->fetchColumn(); } public function lastInsertId() { return $this->db->lastInsertId(); } }
в PDO значения завернуты в массив, а если и плейсхолдеры юзаем, то добавочно придаем ключ ко значению
@GTank ясно в классе БД у тебя принимается массив, значит верни как было) @MouseZver давно не тренировался программировать)
Раз и на всю жизнь. http://phpfaq.ru/pdo/pdo_wrapper http://phpfaq.ru/pdo/fetch --- Добавлено --- Уязвимость топ1 --- Добавлено --- валидация всякой грязи приводил недавно: https://php.ru/forum/threads/proverit-unikalnost-imeni-v-baze-dannyx.71764/#post-576484 --- Добавлено --- Забил на пхп и ушел в майнкрафт мочить свой сервер
ваш метод public function query можно заменить одной строкой с использованием той обвертки: PHP: prepare ( 'SELECT .... = :email', [ 'email' => $value ] ) -> rowCount();
Хреновый класс валидации нарыл, поэтому с ним каши и не сваришь. Даже если ты в него добавишь проверку e-mail, потом тебе надо будет добавить ещё какую-нибудь комплексную проверку, и опять что-ли расширять этот класс? rules должны быть экземплярами классов, или же должен приниматься callable
https://github.com/Respect/Validation - вот вроде неплохой пакет валидации, независимый от фреймворков