Недавно я думал о том, как использовать Laravel для дальнейшей разработки другой среды разработки. Прочитав множество материалов и документов о фреймворке Laravel, я, наконец, остановился на слое Laravel Model.
Я обнаружил, что еще многое предстоит узнать о модели, среди которых выделяются события.
Далее будет кратко описано использование событий модели от «шаблона наблюдателя» до «системы событий Laravel», а затем до «событий модели».
Шаблон наблюдателя
Define a one-to-many dependency between objects so that when one object changes state, all its dependents aer notified and updated automatically.
Определите зависимость «один ко многим» между объектами, чтобы при изменении состояния объекта все объекты, зависящие от него, получали уведомление и автоматически обновлялись.
Как показано на рисунке выше (взято из книги «Шаблоны проектирования Head First»), он в основном состоит из четырех частей:
-
Субъект наблюдаемый. Это интерфейс или абстрактный класс, определяющий обязанности, которые должен выполнять наблюдаемый объект, он должен иметь возможность динамически добавлять и отменять наблюдателя, управлять наблюдателем и уведомлять наблюдателя.
-
Наблюдатель Наблюдатель. После того, как наблюдатель получает сообщение, он выполняет операцию обновления для обработки полученной информации.
-
ConcreteSubject конкретный наблюдаемый. Определите собственную бизнес-логику наблюдателя и определите, какие события следует уведомлять.
-
ConcreteObserver Конкретный наблюдатель. Каждый наблюдатель обрабатывает информацию по-своему, и у каждого наблюдателя своя логика обработки.
Преимущества шаблона наблюдателя
Наблюдатель и наблюдаемое абстрактно связаны, и очень легко расширить, добавить ли наблюдателя или наблюдаемое.
В соответствии с принципом единой ответственности ответственность каждого класса является единственной, поэтому, как соединить каждую отдельную ответственность в настоящую сложную логическую связь, режим наблюдателя может играть роль моста.
Паттерн Наблюдатель — типичный пример слабой связи.
Система событий Laravel
Во фреймворке Laravel есть механизм событий, который является хорошим способом разделения приложений, потому что у события может быть несколько независимых слушателей. Например, если вы хотите отправлять текстовое сообщение или уведомление DingTalk пользователю или оператору каждый раз, когда создается заказ или статус заказа меняется с «неоплаченный на оплаченный». Вы можете просто инициировать событие OrderSaving и позволить слушателю преобразовать его в текстовое сообщение или уведомление DingTalk после его получения, так что вам не нужно объединять «бизнес-код заказа» и код «уведомления о сообщении», и играют роль эффекта «развязки».
События Laravel предоставляют простую реализацию наблюдателя, которая подписывается и прослушивает различные события, происходящие в приложении. Класс события хранится вapp/Events
каталог, а прослушиватели этих событий хранятся вapp/Listeners
Под содержанием. Эти каталоги можно создать с помощью Artisan-команд.
В соответствии с ролью ServiceProvider, когда программа выполняется, она будет автоматически загружена, поэтому в системе событий Laravel EventServiceProvider действует как мост между событиями и слушателями, то есть EventServiceProvider можно использовать для загрузки ассоциации между событиями. и Listeners в систему.
Из этого также видно, что Событие соответствует нескольким Слушателям, а это означает, что его могут отслеживать несколько Слушателей.
Точно так же замыкания на основе событий также могут быть зарегистрированы в методе загрузки.
/**
* 注册应用程序中的任何其他事件。
*
* @return void
*/
public function boot()
{
parent::boot();
Event::listen('event.name', function ($foo, $bar) {
//
});
}
В качестве примера возьмем Model Event, потому что Model Event основан на системе Laravel Event.
Более того, по сравнению с Laravel Event, в обычной логической обработке глобальная функция event() в основном используется для запуска событий, что представляет собой ручной механизм запуска.
В событии модели можно настроить «автоматическое» событие триггера в узле жизненного цикла модели.
Model Events
Работа модели в основном включает в себя следующие узлы жизни:
узел | узел | узел |
---|---|---|
retrieved | creating | created |
updating | updated | saving |
saved | deleting | deleted |
restoring | restored |
The retrieved event will fire when an existing model is retrieved from the database. When a new model is saved for the first time, the creating and created events will fire. If a model already existed in the database and the save method is called, the updating / updated events will fire. However, in both cases, the saving / saved events will fire.
Я считаю, что это легче понять, но его нет в базе данных, в первый раз
save
час,creating
а такжеcreated
Вызываются два события, аналогично, если оно есть в базе данных, выполнитьsave
метод,updating
а такжеupdated
Называются два события.
Ниже приведен пример использования Laravel Event для создания модели заказа.
php artisan make:model Order -m
События и слушатели
1.Регистрация события и слушателя
Аналогичным образом зарегистрируйте ассоциацию с EventServiceProvider:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'App\Events\OrderSavingEvent' => [
'App\Listeners\OrderSavingListener',
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
//
}
}
2.Отправка события сохранения в модели заказа
<?php
namespace App;
use App\Events\OrderSavingEvent;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
protected $dispatchesEvents = [
'saving' => OrderSavingEvent::class,
];
}
3.Создайте классы Event и Listener
php artisan event:generate
Порядок привязки при сохранении события
<?php
namespace App\Events;
use App\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class OrderSavingEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $order;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Order $order) {
$this->order = $order;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
4.Напишите класс Listener для обработки логики прослушивания
<?php
namespace App\Listeners;
use App\Events\OrderSavingEvent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderSavingListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param OrderSavingEvent $event
* @return void
*/
public function handle(OrderSavingEvent $event) {
info($event->order);
}
}
5.контрольная работа
$order = new Order();
$order->name = 'good_name_2';
$order->save();
результат операции:
[2018-03-29 12:30:24] testing.INFO: {"name":"good_name_2"}
Шаблон наблюдателя
Если вы прослушиваете несколько событий в рамках одной и той же модели, вы не всегда можете создать соответствующий класс прослушивателя для каждого события. Laravel предоставляет удобный метод: создайте класс наблюдателя, агрегируйте все события в этот класс, а затем зарегистрируйте класс наблюдателя в загрузке AppServiceProvider:
<?php
namespace App\Providers;
use App\Observers\OrderObserver;
use App\Order;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Order::observe(OrderObserver::class);
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}
Конкретный класс наблюдателя:
<?php
namespace App\Observers;
use App\Order;
class OrderObserver {
/**
* 监听订单创建事件
* @param Order $order
*/
public function creating(Order $order) {
info('creating');
info($order);
}
public function created(Order $order) {
info('created');
info($order);
}
/**
* 监听订单保存事件
* @param Order $order
*/
public function saving(Order $order) {
info('saving');
info($order);
}
public function saved(Order $order) {
info('saved');
info($order);
}
}
контрольная работа:
$order = new Order();
$order->name = 'good_name';
$order->save();
текущий результат:
[2018-03-27 15:04:02] testing.INFO: saving
[2018-03-27 15:04:02] testing.INFO: {"name":"good_name"}
[2018-03-27 15:04:02] testing.INFO: creating
[2018-03-27 15:04:02] testing.INFO: {"name":"good_name"}
[2018-03-27 15:04:02] testing.INFO: created
[2018-03-27 15:04:02] testing.INFO: {"name":"good_name","updated_at":"2018-03-27 15:04:02","created_at":"2018-03-27 15:04:02","id":1}
[2018-03-27 15:04:02] testing.INFO: saved
[2018-03-27 15:04:02] testing.INFO: {"name":"good_name","updated_at":"2018-03-27 15:04:02","created_at":"2018-03-27 15:04:02","id":1}
Обновите заказ еще раз:
$order = Order::find(1);
$order->name = 'good_name3';
$order->save();
В этот момент события создания и создания не будут запущены. текущий результат:
[2018-03-27 15:11:11] testing.INFO: saving
[2018-03-27 15:11:11] testing.INFO: {"id":1,"name":"good_name3","created_at":"2018-03-27 15:04:02","updated_at":"2018-03-27 15:04:02"}
[2018-03-27 15:11:11] testing.INFO: saved
[2018-03-27 15:11:11] testing.INFO: {"id":1,"name":"good_name3","created_at":"2018-03-27 15:04:02","updated_at":"2018-03-27 15:11:11"}
Суммировать
Роль шаблона наблюдателя заключается в том, что наблюдатель и наблюдаемое абстрактно связаны.Когда объект меняет состояние, все наблюдатели, которые зависят от него, будут уведомлены и выполнят соответствующую логическую обработку. Система событий Laravel — достойный пример.
Далее, давайте взглянем на принцип реализации кода, стоящий за этим.
"Продолжение следует"