Laravel. Наблюдатели за событиями Eloquent

26.11.2020

Теги: LaravelPHPWeb-разработкаКлассСобытиеТеорияФреймворк

Наблюдатели предоставляют механизм, который позволяет контролировать каждый процесс, происходящий с базой данных. Список событий, которые можно использовать при работе с базой данных, можно посмотреть в трейте HasEvents. Это retrieved — при извлечении модели из базы данных, creating — перед записью новой модели в базу данных, created — после записи новой модели в базу данных и так далее.

namespace Illuminate\Database\Eloquent\Concerns;

use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Events\NullDispatcher;
use Illuminate\Support\Arr;
use InvalidArgumentException;

trait HasEvents {
    /**
     * Get the observable event names.
     *
     * @return array
     */
    public function getObservableEvents() {
        return array_merge(
            [
                'retrieved', 'creating', 'created', 'updating', 'updated',
                'saving', 'saved', 'restoring', 'restored', 'replicating',
                'deleting', 'deleted', 'forceDeleted',
            ],
            $this->observables
        );
    }
    /* ... */
}

Создадим нового поставщика услуг:

> php artisan make:provider EloquentEventServiceProvider
namespace App\Providers;

use App\Models\Page;
use Illuminate\Support\ServiceProvider;

class EloquentEventServiceProvider extends ServiceProvider {
    /**
     * Register services.
     *
     * @return void
     */
    public function register() {
        // ...
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot() {
        Page::creating(function ($page) {
            $page->name = $page->name . ' (создана ' . auth()->user()->name . ')';
        });
    }
}

Добавим нового поставщика услуг в config/app.php:

return [
    /* ... */
    'providers' => [
        /* ... */
        App\Providers\EloquentEventServiceProvider::class,
    ]
    /* ... */
]

Теперь перед добавлением новой страницы в базу данных к ее названию добавляется имя автора, который ее создал.

Если нужно наблюдать за множеством событий для разных моделей (Page, Post, Category), то неудобно, что все они будут в методе boot() сервис-провайдера EloquentEventServiceProvider. Давайте создадим отдельную директорию app/Observers и разместим в ней файл класса PageObserver.php.

<?php
namespace App\Observers;

use App\Models\Page;

class PageObserver {

    /*
     * Срабатывает перед записью новой страницы
     */
    public function creating(Page $page) {
        $page->name = 'Перед созданием, ' . $page->name;
    }

    /*
     * Срабатывает при извлечении из базы данных
     */
    public function retrieved(Page $page) {
        $page->name = 'При извлечении, ' . $page->name;
    }

    /*
     * Срабатывает перед удалением страницы из БД
     */
    public function deleting(Page $page) {
        return false;
    }
}

А в сервис-провайдере уже не будем обрабатывать события, а только укажем класс, который будет это делать. Другими словами — зарегистрируем наблюдателя за событиями модели Page.

namespace App\Providers;

use App\Models\Page;
use App\Observers\PageObserver;
use Illuminate\Support\ServiceProvider;

class EloquentEventServiceProvider extends ServiceProvider {
    /**
     * Register services.
     *
     * @return void
     */
    public function register() {
        // ...
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot() {
        Page::observe(PageObserver::class);
    }
}

Поскольку метод deleting() возвращает false — страницу теперь вообще нельзя удалить.

Наблюдатели работают с предопределенными событиями, которые происходят только в Eloquent Models (создание записи, обновление записи, удаление и т.д.). События создает сам разработчик, они не определены заранее и могут использоваться где угодно, а не только в моделях. Поэтому мы разместили класс PageObserver в отдельной директории app/Observers, а не в директории app/Listeners.

Поиск: Laravel • PHP • Web-разработка • Класс • Событие • Теория • Фреймворк

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.