Форум программистов, компьютерный форум, киберфорум
Наши страницы
PHP: ООП
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
CoolTuzic
0 / 0 / 2
Регистрация: 27.03.2013
Сообщений: 58
#1

Нужен совет по написанию класса валидатора

21.07.2018, 22:00. Просмотров 709. Ответов 3

Привет. Пишу свой велосипед т.е. OOP, MVC фреймворк. В процессе решил не писать проверки в моделе Аккаунта, а написать отдельный класс валидации форм (в итоге я его стащил с github =)).

Идея заключалась в том, что к полю можно применить несколько методов валидации, допустим:
  1. Поле логин обязательно к заполнению.
  2. Логин должен состоять только из русскиз букв.
  3. Логин должен состоять не менее чем из 3-х символов.


То есть чтобы для каждого неверного действия вываливалось по 1-му сообщению, а не пачкой или вообще в одну строчку.

Код, который я нарыл рабочий на 100%, но в итоге столкнулся с тем, что не могу с помощью этого класса проверить, скажем email на существовании в БД…

В ситуации, когда в базе данных уже есть такой пароль, email или логин нужно показать сообщение, что таковые имеются, но я не доганяю, что нужно делать. Лезть в БД в этом класе нет смысла, потому что это задача модели аккаунта.

В этом классе возможно сделать такие проверки? Может подскажите другой класс примерно такой же сложности.

В общем буду рад любому дельному совету.


Код валидатора:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
 
        }
    }
На всякий случай подключение к БД, а так же работа с таблицами в ней (SELECT,INSERT) и т.п. у меня выглядит так:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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();
    }
 
}
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.07.2018, 22:00
Ответы с готовыми решениями:

нужен совет
Здравствуйте В этом году нужно делать дипломный проект сейчас уже надо...

Нужен технический совет
Здравствуйте, может быть вопрос не в той теме, но не знаю куда обратиться,...

Нужен Теоретический совет
Добрый день, натолкните на мысль в какую сторону повернуться. Нужно...

Нужен совет по удалению левых ссылок
Проверил сайт на наличие внешних ссылок. Нашлось 5 штук. Скачал весь сайт на...

HTML+PHP+форма. Нужен совет.
Есть обычная HTML форма, для добавления продукта. В ней есть много полей:...

3
tarasalk
1125 / 655 / 268
Регистрация: 13.06.2013
Сообщений: 2,310
22.07.2018, 18:03 #2
Цитата Сообщение от CoolTuzic Посмотреть сообщение
не могу с помощью этого класса проверить, скажем email на существовании в БД…
И не надо. Эти проверки на разных уровнях.
Данные от юзера проверяются в самом начале, например в контроллере.
Email проверяется в модели и если косяк бросается эксепшен. Этот эксепшен ловится например в контроллере и в красивом виде выдается юзеру. А можно и где то в другом месте поймать, например в CLI скриптах красота уже не нужна, нужно записать в логи стек трейс ошибки.

Валидатор странный. Писанины много и нельзя сделать несколько независимых валидаторов. Надо было с ларавела стащить , правда он там весь фреймворк за собой потянет.
0
CoolTuzic
0 / 0 / 2
Регистрация: 27.03.2013
Сообщений: 58
22.07.2018, 21:27  [ТС] #3
Цитата Сообщение от tarasalk Посмотреть сообщение
Email проверяется в модели и если косяк бросается эксепшен. Этот эксепшен ловится например в контроллере и в красивом виде выдается юзеру. А можно и где то в другом месте поймать, например в CLI скриптах красота уже не нужна, нужно записать в логи стек трейс ошибки.
Насчёт исключений... У меня ведь обычный массив =) А вот насчёт CLI и >> логи стек трейс ошибки. Вообще ничего не понятно =)

Цитата Сообщение от tarasalk Посмотреть сообщение
Валидатор странный. Писанины много и нельзя сделать несколько независимых валидаторов. Надо было с ларавела стащить , правда он там весь фреймворк за собой потянет.
Ну вот какой нашел =)

На данный момент сделал вот так:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    
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: /");
            }
        }
        $this->set(compact('errors','name','email','password'));
    }
Оставить это всё так и не париться? Для джуна сойдёт? Хотя конечно хочется отдельный класс =)
0
tarasalk
1125 / 655 / 268
Регистрация: 13.06.2013
Сообщений: 2,310
22.07.2018, 22:36 #4
Лучший ответ Сообщение было отмечено CoolTuzic как решение

Решение

Цитата Сообщение от CoolTuzic Посмотреть сообщение
Насчёт исключений... У меня ведь обычный массив
И что? Ловите эксепшен и в блоке catch записываете ошибку в массив.

Цитата Сообщение от CoolTuzic Посмотреть сообщение
А вот насчёт CLI и >> логи стек трейс ошибки. Вообще ничего не понятно =)
Непонятные слова надо гуглить, я не справочник.
cli - скрипты запускаемые через командную строку, а не браузер. Их обычно пишут когда нужно делать что-то периодические, например ежедневная рассылка на почту. Запускаются через cron.
стек трейс - список ошибок. Видно какие классы/методы вызывались, номер строки итд... Очень помогает находить ошибку.

Цитата Сообщение от CoolTuzic Посмотреть сообщение
Оставить это всё так и не париться?
Я хз какие у вас цели. Писать свой фреймворк на мой взгляд изначально бред.
1) Долго.
2) Навыки написания фреймворков не особо востребованы.
3) Опыта не хватит написать что-то достойное.

Если просто абстрагировано посмотреть, то мне не нравится.
1) Модель это слой. Грубо говоря он может состоять из нескольких классов(сервисы, репозитории, сущности...). Ваш подход приведет к появлению божественных классов, которые умеют все и вся.
2) Проверка и текст ошибок разделены, что затрудняет сопровождение кода. Допустим требования поменялись, я поменяю метод checkName, а сообщение об ошибке поменять забуду. В больших проектах этот метод может вызываться десятки и сотни раз...
3) Проверка email должна быть внутри методы register, это часть ее бизнес логики.
4) Я бы разделил registerAction на два метода. а) показ шаблона (GET). б) регистрация (POST). Как правило чем проще методы, тем легче их сопровождать.

Цитата Сообщение от CoolTuzic Посмотреть сообщение
Для джуна сойдёт?
Имхо. Для джуна главное желание учиться, уметь гуглить и прислушиваться к более опытным товарищам. Код не особо важен на первом этапе. В командном проекте вам все равно впихнут другой движок со своими велосипедами.
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.07.2018, 22:36

Singleton для PDO. Нужен совет
Ребята, не кидайте помидорами если что. Нужен простой класс БД для работы с...

Нужен совет по написанию программы на C#
Здравствуйте. Так как считаю мнения людей сидящих на этом форуме авторитетным,...

Нужен совет по написанию игры
В общем, на следующий год мне сдавать курсовую - некую программу на Pascal....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru