Pull to refresh

Comments 11

Если я все верно понимаю, ваш PriceValidator вынесен в отдельный метод только для того что бы написать пару логов. Без логов можно было бы использовать match. Также в Yii2 целая куча встроенных валидаторов.

Кстати не уверен что логировать в валидаторе — хорошее решение. Хотя если не в нем, то где? Опытные Yii'сты поправьте меня.
Изначально идея вынести все кастомные валидации в отдельный файл у меня появилась из-за того, что клиент просит практически для каждого поля свой текст ошибки. Не просто «Некорректный ввод» или «Не должно быть пустым», а «ИНН должен состоять из 10 цифр», «Ваш телефон не подходит для нашего региона», при этом клиент очень щепетильно относится и к вопросу несоответствия информации на разных формах сайта.

Например при регистрации пишется «Некорректный номер телефона» (регистрацию делал 2 месяца назад), а при изменении номера в личном кабинете «Номер набран неверно» (делал пару недель назад и благополучно не обратил внимание, что валидация регистрации у меня проходила через модель-посредник). Таким образом я и решил запихнуть все кастомные валидации в одно место, чтобы их было удобней поддерживать/изменять, а не приходилось бегать по десяткам моделей и для каждой менять rules и при этом не совершать элементарных опечаток.

Не нужно бояться "захламления" папок валидаторами. Это самый правильный подход. Каждый класс должен выполнять то что ему положено.


  public function traitPrice($attribute, $params, $validator ) {
        $pattern = "/^[8|+7]922\d{7}$/uism";
        if (preg_match($pattern, $this->$attribute) == 0) {
            $this->addError($attribute, 'Принимаются только номера мегафона в Перми!');
            $region = Yii::$app->newRegions->addRegionByPhone( $this->$attribute );
            Yii::$app->log->write("Потенциальный клиент из другого региона: " . $region);
}

А тут у вас смешение логики, и валидация и какое-то добавление… возможно в базу.
Тут лучше кинуть событие о том что левый регион, потому как тут явно логика может поменяться. И почему функция traitPrice обрабатывает номер телефона?

если для бизнеса важно отлавливать некорректные валидации, для анализа взаимодействия с ui например, то кидать event, который слушать и обрабатывать

Event, точно! Спасибо, совсем забыл о них. Тогда можно создать директорию под события. Потому что, как demimurych говорил ниже:
разбросать все нужные мне классы так как хочется

Главное PSR (вроде бы 4й) соблюдать, именование, неймспейсы, а дальше, к примеру, создать директорию ./events/signup, а в ней PhoneMismatchEvent, PotentialClientEvent и т.д.
Простите если вдруг я что-то забыл, но насколько я помню, Yii2 никогда не накладывал жестких ограничений на размещение чего-либо где-либо. Иначе говоря я всегда мог разбросать все нужные мне классы так как хочется мне, а не держать контроллеры в папке контроллеры модели в папке моделс и так далее. Не исключаю что с валидаторами ровно тоже самое.
UFO just landed and posted this here
Несколько десяткой файлов в каталоге Вам кажется много (хотя никто не запрещает их группировать в подкаталоги).
А как тогда несколько сотен/тысяч строк в файле с трейтом (который нужно постоянно поддерживать), удобно так работать?
А если нужно сообщения об ошибках вынести в одно место, то достаточно использовать Yii::t().

P.S.: на истину также не претендую.

Не претендую на истинность высказываний, но Ваше решение очень плохо пахнет… Yii в качестве валидатора может принимать любой callable (ведь так?). Поэтому я бы предпочел либо сделать класс с набором статических методов-валидаторов [CustomValidators::class, 'phoneValidator'], либо создавать экземпляр класса и указывать метод [new CustomValidators(), 'phoneValidator'], либо можно вообще наполнить статическое свойство yii\validators\Validator::$builtInValidators конфигами часто используемых валидаторов и писать так: ['propertyToValidate', 'phone']. Но использовать для этого трейт и пихать все нужные и ненужные методы в класс… Почему-то мне кажется, это не самое лучшее решение…
Я предпочитаю для часто используемых валидаторов использовать последний метод (для номеров телефонов, например), а в остальных случаях создавать новый класс и явно его указывать.
// Все выше сказанное является абсолютным ИМХО

Вроде должен, но, по моему, в документации используется только string т.е. если вы напишете в массиве с правилами
['myValidatedField', 'validationMethod']
, то надо объявить в текущем классе метод validationMethod с модификатором доступа public. Вы, вероятнее всего, это знаете, поэтому пишу на всякий случай для тех, кто не знает ;-)
А на счет любых callable не проверял, но недавно пробовал сделать что-то вроде
[$this, 'validationMethod']
, по типу как вы писали, и у меня било ошибку.

Вы, к сожалению, правы на счет последнего. Обычный callable Yii2 в качестве валидатора не принимает (хотя очень хотелось бы). Достаточно посмотреть в код \yii\validators\Validator::createValidator


Зато он принимает Closure! И тогда можно использовать одну из фич PHP7 Closure::fromCallable:


\Closure::fromCallable([$this, 'validationMethod'])

// Опять же, я не проверял. В теории, должно работать. Но идея с трейтами мне до сих пор не нравится.

Sign up to leave a comment.

Articles