Загрузка и инициализация Моделей с Трейтами

Загрузка и инициализация Моделей с Трейтами

Одним из преимуществ Eloquent ORM его сочетаемость с трейтами — когда вы используете Модель Eloquent, то вы можете выполнить дополнительную логику, прежде чем начнете использовать саму модель.

Метод загрузки волшебный, так как вы можете прикрепить Трейт к Модели. И, если вы положите несколько методов в этот трейт, то они будут вызваны, когда вы начнете использовать Модель. Названия методов должны следовать шаблону boot{Trait} и initialize{Trait}, позволяя вам повторно использовать один и тот же код в нескольких моделях.

Загрузка и инициализация

Разница между ними очень проста: Загрузка работает статически , а Инициализация — динамически. Загрузка затронет все экземпляры модели, а инициализация будет работать только для её экземпляра.

Чтобы лучше проиллюстрировать, как всё это работает, давайте сделаем трейт под названием HasRandomToken. Эта трейт имеет две задачи по данной модели Eloquent.

  1. Добавить Событие в журнал при создании Модели: кто это сделал.
  2. Добавьте к Модели случайную строку в качестве токена.

Первая задача — просто узнать, что аутентифицированный пользователь создал новую модель. Второй позволит нашей модели автоматически получать случайный токен, чтобы не делать этого вручную для каждой части нашего приложения.

Итак, у нас есть Модель:

namespace App;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

trait HasToken
{
    /**
     * Boot the trait
     *
     * @return void
     */
    protected function bootHasToken()
    {
        static::created(function ($model) {
            // Журналируем, кто создал Модель
            Log::info('Token for ' . class_basename($model) . ' created by ' . Auth::user()->getKey());
        });
    }
    
    /**
     * Initialize the trait
     *
     * @return void
     */
    protected function initializeHasToken()
    {
        // Автоматически создаём случайный токен
        $this->token = Str::random(100);
    }
}

Загрузка

Метод загрузки будет работать над статической моделью. Например, если вы добавите этот трейт в модель Authentication, все, что вы делаете с помощью этого метода, будет влиять на эту модель статически.

Имя метода должно соответствовать шаблону boot{TraitName}.

Это очень удобно для добавления обратных вызовов событиям eloquent, таким как creating или retrieving для данной Модели, поскольку они работают статически.

/**
 * Boot the trait
 * 
 * @return void
 */
protected function bootHasToken()
{
    static::created(function ($model) {
        //  Журналируем, кто создал Модель
        Log::info('Token for ' . 
            class_basename($model) . 
           ' created by ' . 
           Auth::user()->getKey()
        );
    });
}

Это очень хорошо продумано: загрузка модели не будет выполняться дважды, а только при необходимости. Вам не нужно бояться вызвать bootHasToken() несколько раз, класс модели Eloquent ORM будет отслеживать загруженные модели.

Инициализация

Хорошо, мы можем делать некоторые вещи на статическом уровне, используя метод загрузки, но чтобы манипулировать самим экземпляром модели, нам нужно использовать метод инициализации. Вы можете создать инициализатор, используя шаблон initialize{Trait}.

/**
 * Initialize the trait
 *
 * @return void
 */
protected function initializeHasToken()
{
    // Автоматически создаём случайный токен
    $this->token = Str::random(100);
}

Инициализация будет выполняться каждый раз, когда создается новая Модель.

И это вся магия.

Автор: Italo Baeza
Перевод: Demiurge Ash