Comments 11
Кстати не уверен что логировать в валидаторе — хорошее решение. Хотя если не в нем, то где? Опытные Yii'сты поправьте меня.
Например при регистрации пишется «Некорректный номер телефона» (регистрацию делал 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, который слушать и обрабатывать
разбросать все нужные мне классы так как хочется
Главное PSR (вроде бы 4й) соблюдать, именование, неймспейсы, а дальше, к примеру, создать директорию ./events/signup, а в ней PhoneMismatchEvent, PotentialClientEvent и т.д.
А как тогда несколько сотен/тысяч строк в файле с трейтом (который нужно постоянно поддерживать), удобно так работать?
А если нужно сообщения об ошибках вынести в одно место, то достаточно использовать
Yii::t()
.P.S.: на истину также не претендую.
Не претендую на истинность высказываний, но Ваше решение очень плохо пахнет… Yii в качестве валидатора может принимать любой callable (ведь так?). Поэтому я бы предпочел либо сделать класс с набором статических методов-валидаторов [CustomValidators::class, 'phoneValidator'], либо создавать экземпляр класса и указывать метод [new CustomValidators(), 'phoneValidator'], либо можно вообще наполнить статическое свойство yii\validators\Validator::$builtInValidators конфигами часто используемых валидаторов и писать так: ['propertyToValidate', 'phone']. Но использовать для этого трейт и пихать все нужные и ненужные методы в класс… Почему-то мне кажется, это не самое лучшее решение…
Я предпочитаю для часто используемых валидаторов использовать последний метод (для номеров телефонов, например), а в остальных случаях создавать новый класс и явно его указывать.
// Все выше сказанное является абсолютным ИМХО
['myValidatedField', 'validationMethod']
, то надо объявить в текущем классе метод validationMethod с модификатором доступа public. Вы, вероятнее всего, это знаете, поэтому пишу на всякий случай для тех, кто не знает ;-)А на счет любых callable не проверял, но недавно пробовал сделать что-то вроде
[$this, 'validationMethod']
, по типу как вы писали, и у меня било ошибку.Вы, к сожалению, правы на счет последнего. Обычный callable
Yii2 в качестве валидатора не принимает (хотя очень хотелось бы). Достаточно посмотреть в код \yii\validators\Validator::createValidator
Зато он принимает Closure! И тогда можно использовать одну из фич PHP7 Closure::fromCallable
:
\Closure::fromCallable([$this, 'validationMethod'])
// Опять же, я не проверял. В теории, должно работать. Но идея с трейтами мне до сих пор не нравится.
Собственные валидации полей для Rules в одном классе