Итак, узнал сегодня небольшую фитчу Laravel/Eloquent, которая практически не описана и лишь вскользь упомянута в документации фреймовика.
Перейдите к TL;DR, если вы просто хотите увидеть эту фичу.
Возможно, вы уже знаете, что можно добавлять статические boot()-методы к Eloquent-модели, которые будут выполнены при ее загрузке. Это можно использовать, например, привязываясь к событиям модели, если это необходимо. Например, вы можете организовать email-уведомление, каждый раз, когда будет создан новый пользователь(неудачный пример), но вы могли бы описать это следующим образом:
Но что если вы хотите поместить это с trait?
Рассмотрим такой сценарий; необходимо организовать поиск в диапазоне моделей. Конечно, можно создать новый класс SearchableModel, унаследовав его от Eloquent\Model, но хотелось бы написать таким образом, чтобы функционал был легко переносим в другие проекты, не привязываясь к конкретному приложению. Трейт здесь подойдет как-никак лучше, потому что он легко переносим и относительно ненавязчив, подключая который вы получаете дополнительный функционал, который может быть легко переопределен.
Итак, я создал SearchableTrait.
Довольно просто пока, мы вызываем метод $model->search('query'), возвращающий модели, соответствующие критериям запроса.
Тем не менее, вместо непосредственного поиска по базе данных я планирую использовать сторонний поиск по приложению(если кому интересно, elasticsearch), использующий собственную индексацию, которая требует настройки индекса каждой строки вручную.
Но куда мне вставить этот код?
Я мог бы поместить его в boot()-метод модели, но там он может быть затерт, тем самым нарушая мой поиск и уничтожая любой шанс быть повторно использованным.
TL; DR
Ребята из Laravel явно предусмотрели, каким образом подгружать ваши трейты, определяя специальное метод, как в Eloquent-модели, к примеру:
Таким образом, здесь присутствует небольшая классическая магия Eloquent. Если у вас есть статический метод в трейте, который называется по принципу boot[NameOfTrait], то он будет выполнен также, как статический boot()-метод модели. Какое удобное место для регистрации событий своей модели.
Пример в документации по Laravel, реализует этот трюк при регистрации глобального скоупа, для перехвата всех запущенных запросов, при мягком удаление моделей.
Конечно же, кроме этой фичи, есть и другие хорошие способы для достижения того же результата, но всегда приятно держать плохо документированные тонкости в своем арсенале, чтобы воспользоваться ими в случае необходимости.
Перейдите к 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, реализует этот трюк при регистрации глобального скоупа, для перехвата всех запущенных запросов, при мягком удаление моделей.
Конечно же, кроме этой фичи, есть и другие хорошие способы для достижения того же результата, но всегда приятно держать плохо документированные тонкости в своем арсенале, чтобы воспользоваться ими в случае необходимости.