Итак, узнал сегодня небольшую фитчу Laravel/Eloquent, которая практически не описана, и представляет лишь скользкое упоминание в документации фреймовика.
Перейдите к TL;DR, если вы просто хотите увидеть эту фитчу.
Возможно, вы уже знаете, что можно добавлять статические boot()-методы к Eloquent-модели, которые будут выполнены при ее загрузке. Это можно использовать, например, привязываясь к событиям модели, если это необходимо. Например, вы можете организовать email-уведомление, каждый раз, когда будет создан новый пользователь(неудачный пример), но вы могли бы описать это следующим образом:
class User extends Eloquent { public static function boot() { parent::boot(); static::created(function($user) { // Send a mailing… }); } }
Но, что если вы хотите поместить это с trait?
Рассмотрим такой сценарий; необходимо организовать поиск в диапазоне моделей. Конечно, можно создать новый класс SearchableModel, унаследовав его от Eloquent\Model, но хотелось бы написать таким образом, чтобы функционал был легко переносим в другие проекты, не привязываясь к конкретному приложению. Трейт здесь подойдет как-никак лучше, потому что он легко переносим и относительно ненавязчив, подключая который вы получаете дополнительный функционал, который может быть легко переопределен.
Итак, я создал SearchableTrait.
trait SearchableTrait { public function search($query) { // ... } }
Довольно просто пока, мы вызываем метод $model->search(‘query’), возвращающий модели, соответствующие критериям запроса.
Тем не менее, вместо непосредственного поиска по базе данных я планирую использовать сторонний поиск по приложению(если кому интересно, elasticsearch), использующий собственную индексацию, которая требует настройки индекса каждой строки вручную.
Но куда мне вставить этот код?
Я мог бы поместить его в boot()-метод модели, но там он может быть затерт, тем самым нарушая мой поиск и уничтожая любой шанс быть повторно использованным.
TL; DR
Ребята из Laravel явно предусмотрели, каким образом подгружать ваши трейты, определяя специальное метод, как в Eloquent-модели, к примеру:
trait SearchableTrait { public function search($query) { // ... } public static function bootSearchableTrait() { static::created(function($item){ // Index the item }); } }
Таким образом, здесь присутствует небольшая классическая магия Eloquent. Если у вас есть статический метод в трейте, который называется по принципу boot[NameOfTrait], то он будет выполнен также, как статический boot()-метод модели. Какое удобное место для регистрации событий своей модели.
Пример в документации по Laravel, реализует этот трюк при регистрации глобального скоупа, для перехвата всех запущенных запросов, при мягком удаление моделей.
Конечно же, кроме этой фитчи, есть и другие хорошие способы для достижения того же результата, но всегда приятно держать плохо документированные тонкости в своем арсенале, чтобы воспользоваться ими в случае необходимости.
ссылка на оригинал статьи http://habrahabr.ru/post/259589/
Добавить комментарий