Как вы наверное догадались, хочу рассказать о Yii2 и о том, что ждет новичков в стартапе, который выбрал данный фреймворк. Ни для кого не секрет, что многие фреймворки используют компоненты symfony, дабы не изобретать новый велосипед. Многие, но не Yii, но при этом Yii многое позаимствовал от symfony и впитал в себя лучшее от Ruby on Rails. На github в issues часто можно увидеть предложение по расширению функционала, перенятого у этих фреймворков. В данной статье хотелось бы описать именно те моменты, в которых разработчики Yii не сходятся во мнении с разработчиками других фреймворков.
ActiveRecord
AR — это модель, представляющая собой 1 запись в хранилище, но мало кто знает, что в Yii так же finder прячется за статическим методов find и называется он ActiveQuery.
ActiveQuery
Рассмотрим пример User::find()->andWhere(['username' => 'ok'])->one().
На первый взгляд все логично, не считая того факта, что в коробке в advanced template используется User::findByUsername('ok'). Но если в первом случае мы сможем отвязаться от класса User, передав, к примеру, в конструктор $query = User::find()->andWhere(/*чтотоеще*/), то в «коробочном» варианте вам чтобы добавить условие нужно расширить класс User и перекрыть логику работы в методе findByUsername.
Стоит отметить, что ActiveQuery завязан на класс модели, и если вы хотите добавить default scope, то вам необходимо расшириться от модели и перекрыть вышеупомянутый метод find:
public static function find()
{
return parent::find()->andWhere(['status' => 'active']);
}
Чтобы наложить условие по умолчанию на ActiveQuery, нам нужно расширить ActiveRecord.
Rules или валидация
В гайде по Ruby on Rails на этот счет написано следующее:
1.1 Why Use Validations?
Validations are used to ensure that only valid data is saved into your database.
yiisoft/core-developers так не думают, и считают, что валидировать нужно только входящие данные от пользователя в форме, а все остальное — это проблема в руках программиста, т.е. вы должны сами отлавливать pdo exception, если уж вдруг что-то пошло не так — ошибок валидации не ждите. Поэтому в коробке минимально проверяют данные перед записью в бд. Быть может, это связано с экономией на производительности:
— все валидаторы создаются сразу при инициализации модели, не зависимо от сценария;
— рендер input type=text (на спичках).
Кстати говоря, о производительности. Тесты, размещенные в интернете, были произведены при минимальном кол-ве кода Yii, то есть сейчас картинка явно будет отличаться в худшую сторону.
Безопасность или производительность — каждый решает сам. В коробке advanced app — производительность.
Но даже выбрав безопасность, вы можете смело забывать про «коробочные поведения для атрибутов», которые завязаны на события beforeInsert и beforeUpdate, а события beforeValidate всего лишь одно, или необходимо модернизировать value свойство с проверкой $event->sender->isNewRecord.
Так же выбрав безопасность следует забыть про метод link, который должен связывать 2 модели между собой по foreign key. Связано это с тем, что метод link сохраняет модель после «перелиновки» и это поведение неизбежно, причем сохранение идет без валидации, следовательно вышеупомянутые поведения для атрибутов отработаны не будут и мы получим исключение pdo о том, что поле обязательно к заполнению. Валидировать до метода link мы не можем, так как для foreign keys существует валидатор exist, который провалится, или мы должны делать выборочную валидацию, причем необходимо передавать белый список атрибутов, и при добавлении нового атрибута в модель будьте готовы перелопатить кучу кода.
Безопасность или плюшки из коробки — решать вам.
ActiveRelation
Здесь речь пойдет о связи моделей между собой или понятие модуля в Yii.
Как известно — модуль — самодостаточная единица приложения. Рассмотрим пример: подключив 2 модуля User и BankAccount, мы должны связать между собой модели User и UserAccount. Это я оставлю вам как домашнее задание, так как разработчики сами пока не могут дать на это ответ. Именно поэтому мне кажется, User и Rbac в коробке yii, а не в виде расширений. А пока посмотрим на то, что придумано давно symfony.
Тем, кто всерьез решит сделать «домашку», надо учесть, что модели невозможно конфигурировать по ряду причин, одной из них является создание модели, как связанной по ключу.
Если вы решили «домашку», попробуйте решить ее снова, но не перекрывая обе модели из модулей.
Скажем дружно, модулям — ненужно.
На этом статью будем считать оконченной. В довесок ниже будет еще несколько бонусов, но для начала хочу сказать, что я разрабатываю на данном фреймворке более 5 лет (начинал еще с yii 1.x) и мне он нравится своей возможностью конфигурирования компонентов, но в yii2 все больше и больше завязывается на Closure, что не позволяет уже так гибко конфигурировать, как хотелось бы. Возможно, связано это с тем, что в сообществе много фанатов Laravel? Так же хотелось бы поблагодарить разработчиков yii2 за их вклад и труд, первый блин всегда комом, второй уже получше.
Бонусы
— Во всех языках программирования при вызове события в него можно передать параметры, в Yii параметры надо передавать при вешании обработчика;
— Бывает и Вика учит «быдлокодить»;
— Мистика алиасов (https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseFileHelper.php#L135).
Любите Yii, помогайте сообществу. Если ваш issue сразу завернули — не расстраивайтесь. Возможно, кто-то позже создаст аналогичное и его не завернут (были и такие случаи). Всем чистого кода, понятных комментариев в нем и отсутствие ошибок в тестах.
P.S. Знаю, что некоторые из разработчиков yii посещают данный ресурс, хотелось бы извиниться перед ними. Возможно, я где то наврал — буду рад любым комментариям ниже.
Автор: oknimdy