Может войдёшь?
Черновики Написать статью Профиль

События

перевод документация 5.х

  1. 1. Введение
  2. 2. Регистрация событий и слушателей
    1. 2.1. Генерация классов событий и слушателей
    2. 2.2. Регистрация событий вручную
  3. 3. Определение событий
  4. 4. Определение слушателей
  5. 5. Слушатели события в очереди
    1. 5.1. Ручной доступ к очереди
  6. 6. Запуск событий
  7. 7. Широковещательные события
    1. 7.1. Конфигурация
    2. 7.2. Помечаем широковещательные события
    3. 7.3. Широковещательные данные
    4. 7.4. Настройка широковещательных событий
    5. 7.5. Использование широковещательных событий
  8. 8. Подписчики событий
    1. 8.1. Написание подписчиков событий
    2. 8.2. Регистрация подписчика события
  9. 9. События фреймворка
Этот перевод актуален для англоязычной документации на (ветка 5.3) , (ветка 5.2) , (ветка 5.1) и (ветка 5.0). Опечатка? Выдели и нажми Ctrl+Enter.

Введение

События в Laravel представлены реализацией паттерна Observer, что позволяет вам подписываться и прослушивать различные события, возникающие в вашем приложения. Как правило, классы событий находятся в папке app/Events, а классы обработчиков событий — в app/Listeners. Если у вас нет этих папок, не переживайте, они будут созданы при создании событий и слушателей с помощью Artisan-команд.

События — отличный способ для разделения различных аспектов вашего приложения, поскольку одно событие может иметь несколько слушателей, независящих друг от друга. Например, вы можете отправлять пользователю Slack-уведомление каждый раз, когда заказ доставлен. Вместо привязки кода обработки заказа к коду Slack-уведомления вы можете просто создать событие OrderShipped, которое сможет получить слушатель и преобразовать в Slack-уведомление.

Регистрация событий и слушателей

Сервис-провайдер EventServiceProvider, включённый в ваше Laravel приложение, предоставляет удобное место для регистрации всех слушателей событий. Свойство listen содержит массив всех событий (ключей) и их слушателей (значения). Конечно, вы можете добавить столько событий в этот массив, сколько требуется вашему приложению. Например, давайте добавим событие OrderShipped:

PHP
/**
 * Слушатель события в вашем приложении.
 *
 * @var array
 */
protected $listen = [
  
'App\Events\OrderShipped' => [
    
'App\Listeners\SendShipmentNotification',
  ],
];

Генерация классов событий и слушателей

Конечно, вручную создавать файлы для каждого события и слушателя затруднительно. Вместо этого добавьте слушателей и события в ваш EventServiceProvider и используйте команду shevent:generate. Эта команда сгенерирует все события и слушателей, которые перечислены в вашем EventServiceProvider.
Конечно, уже существующие события и слушатели останутся нетронутыми:

shphp artisan event:generate

Регистрация событий вручную

Как правило, события должны регистрироваться через массив $listen в EventServiceProvider.

+ 5.3

добавлено в 5.3 ()

Однако, также вы можете вручную регистрировать события на основе замыканий в методе PHPboot() вашего EventServiceProvider:

PHP
/**
 * Регистрация своих событий в приложении.
 *
 * @return void
 */
public function boot()
{
  
parent::boot();

  
Event::listen('event.name', function ($foo$bar) {
    
//
  
});
}
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

Однако, также вы можете регистрировать события вручную с обработчиком событий, используя либо фасад Event, либо реализацию контракта Illuminate\Contracts\Events\Dispatcher

PHP
/**
 * Регистрация своих событий в приложении.
 *
 * @param  \Illuminate\Contracts\Events\Dispatcher  $events
 * @return void
 */
public function boot(DispatcherContract $events)
{
  
parent::boot($events);

  
$events->listen('event.name', function ($foo$bar) {
    
//
  
});
}

Слушатели событий по маске

Вы даже можете регистрировать слушателей, используя символ * как маску, что позволит вам поймать несколько событий для одного слушателя. Такой метод вернёт весь массив данных событий одним параметром:

PHP
Event::listen('event.*', function (array $data) {
  
//
});

Определение событий

Класс события — это просто контейнер данных, содержащий информацию, которая относится к событию.

+ 5.3

добавлено в 5.3 ()

Например, предположим, что наше сгенерированное событие OrderShipped принимает объект Eloquent ORM:

PHP
<?php

namespace App\Events;

use 
App\Order;
use 
Illuminate\Queue\SerializesModels;

class 
OrderShipped
{
  use 
SerializesModels;

  public 
$order;

  
/**
   * Создание нового экземпляра события.
   *
   * @param  Order  $order
   * @return void
   */
  
public function __construct(Order $order)
  {
    
$this->order $order;
  }
}

Как видите, этот класс события не содержит никакой логики. Это просто контейнер для объекта Order. Типаж SerializesModels, используемый событием, корректно сериализирует любые Eloquent модели, если объект события будет сериализирован php-функцией PHPserialize().

+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

Например, предположим, что наше сгенерированное событие PodcastWasPurchased принимает объект Eloquent ORM:

PHP
<?php

namespace App\Events;

use 
App\Podcast;
use 
App\Events\Event;
use 
Illuminate\Queue\SerializesModels;

class 
PodcastWasPurchased extends Event
{
  use 
SerializesModels;

  public 
$podcast;

  
/**
   * Создание нового экземпляра события.
   *
   * @param  Podcast  $podcast
   * @return void
   */
  
public function __construct(Podcast $podcast)
  {
    
$this->podcast $podcast;
  }
}

Как видите, этот класс события не содержит никакой логики. Это просто контейнер для объекта Podcast. Типаж SerializesModels, используемый событием, корректно сериализирует любые Eloquent модели, если объект события будет сериализирован php-функцией PHPserialize().

Определение слушателей

Теперь давайте взглянем на слушателя для нашего примера события. Слушатели событий принимают экземпляр события в свой метод PHPhandle(). Команда shevent:generate автоматически импортирует класс события и указывает тип события в метод PHPhandle(). В методе PHPhandle() вы можете выполнять любые действия, необходимые для ответа на событие.

+ 5.3

добавлено в 5.3 ()

PHP
<?php

namespace App\Listeners;

use 
App\Events\OrderShipped;

class 
SendShipmentNotification
{
  
/**
   * Создание слушателя события.
   *
   * @return void
   */
  
public function __construct()
  {
    
//
  
}

  
/**
   * Обработка события.
   *
   * @param  OrderShipped  $event
   * @return void
   */
  
public function handle(OrderShipped $event)
  {
    
// Доступ к order, используя $event->order...
  
}
}

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

+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

PHP
<?php

namespace App\Listeners;

use 
App\Events\PodcastWasPurchased;
// для версии 5.1 и ранее:
// use Illuminate\Queue\InteractsWithQueue;
// use Illuminate\Contracts\Queue\ShouldQueue;

class EmailPurchaseConfirmation
{
  
/**
   * Создание слушателя события.
   *
   * @return void
   */
  
public function __construct()
  {
    
//
  
}

  
/**
   * Обработка события.
   *
   * @param  PodcastWasPurchased  $event
   * @return void
   */
  
public function handle(PodcastWasPurchased $event)
  {
    
// Доступ к podcast, используя $event->podcast...
  
}
}

Ваши слушатели события могут также указывать тип любых зависимостей, которые необходимы для их конструкторов. Все слушатели события доступны через сервис-контейнер Laravel, поэтому зависимости будут инъецированы автоматически:

PHP
use Illuminate\Contracts\Mail\Mailer;

public function 
__construct(Mailer $mailer)
{
  
$this->mailer $mailer;
}

Остановка распространения события

Иногда, вам необходимо остановить распространение события для других слушателей. Вы можете сделать это, возвратив false из метода PHPhandle() вашего слушателя.

Слушатели события в очереди

Поместить слушателя в очередь может быть полезно, если ваш слушатель будет выполнять медленную задачу, например, отправку e-mail или выполнение HTTP-запроса. Прежде чем помещать слушателей в очередь, не забудьте настроить вашу очередь и запустить слушателя очереди на вашем сервере или в локальной среде разработки.

Чтобы указать, что слушатель должен быть поставлен в очередь, добавьте интерфейс ShouldQueue в класс слушателя. В слушателях, сгенерированных Artisan-командой shevent:generate, уже импортирован этот интерфейс в текущее пространство имен. Так что вы можете сразу использовать его:

PHP
<?php

namespace App\Listeners;

use 
App\Events\OrderShipped;
// для версии 5.1 и ранее:
// use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class 
SendShipmentNotification implements ShouldQueue
{
  
//
}

Вот и всё! Теперь, когда этого слушателя вызывают для события, он будет автоматически поставлен в очередь диспетчером события, использующим систему очереди Laravel. Если никакие исключения не будут выброшены, когда слушатель выполняется из очереди, то задача в очереди будет автоматически удалена после завершения её выполнения.

Ручной доступ к очереди

Если вам необходимо вручную получить доступ к базовым методам очереди слушателя PHPdelete() и PHPrelease(), вы можете сделать это с помощью типажа Illuminate\Queue\InteractsWithQueue. Этот типаж по умолчанию импортирован в сгенерированные слушатели и предоставляет доступ к этим методам:

PHP
<?php

namespace App\Listeners;

use 
App\Events\OrderShipped;
use 
Illuminate\Queue\InteractsWithQueue;
use 
Illuminate\Contracts\Queue\ShouldQueue;

class 
SendShipmentNotification implements ShouldQueue
{
  use 
InteractsWithQueue;

  public function 
handle(OrderShipped $event)
  {
    if (
true) {
      
$this->release(30);
    }
  }
}

Запуск событий

+ 5.3

добавлено в 5.3 ()

Чтобы запустить событие, вы можете передать экземпляр события во вспомогательный метод PHPevent(). Этот метод распространит событие для всех его зарегистрированных слушателей. Поскольку метод PHPevent() доступен глобально, вы можете вызвать его из любого места вашего приложения:

PHP
<?php

namespace App\Http\Controllers;

use 
App\Order;
use 
App\Events\OrderShipped;
use 
App\Http\Controllers\Controller;

class 
OrderController extends Controller
{
  
/**
   * Доставка данного заказа.
   *
   * @param  int  $orderId
   * @return Response
   */
  
public function ship($orderId)
  {
    
$order Order::findOrFail($orderId);

    
// Логика доставки заказа...

    
event(new OrderShipped($order));
  }
}

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

+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

Чтобы запустить событие, вы можете использовать фасад Event, передав экземпляр события методу PHPfire(). Метод PHPfire() распространит событие для всех его зарегистрированных слушателей:

PHP
<?php

namespace App\Http\Controllers;

use 
Event;
use 
App\Podcast;
use 
App\Events\PodcastWasPurchased;
use 
App\Http\Controllers\Controller;

class 
UserController extends Controller
{
  
/**
   * Показать профиль заданного пользователя.
   *
   * @param  int  $userId
   * @param  int  $podcastId
   * @return Response
   */
  
public function purchasePodcast($userId$podcastId)
  {
    
$podcast Podcast::findOrFail($podcastId);

    
// Логика покупки podcast...

    
Event::fire(new PodcastWasPurchased($podcast));
  }
}

Также вы можете использовать глобальную вспомогательную функцию PHPevent() для запуска события:

PHP
event(new PodcastWasPurchased($podcast));

Широковещательные события

Во многих современных веб-приложениях используются веб-сокеты, чтобы реализовать быстро обновляющиеся пользовательские интерфейсы реального времени. Когда некоторые данные обновлены на сервере, сообщение обычно отправляется по websocket соединению, которое будет обработано клиентом.

Чтобы помочь вам в создании этих типов приложений, Laravel упрощает «передачу» ваших событий по websocket соединению. Широковещательные события Laravel позволяют вам совместно использовать те же имена событий между серверным кодом и клиентской платформой JavaScript.

Конфигурация

Все параметры широковещательных событий находятся в конфигурационном файле config/broadcasting.php. Laravel поддерживает несколько широковещательных драйверов из коробки: Pusher, Redis и драйвер log для локальной разработки и отладки. Пример конфигурации включен для каждого из этих драйверов.

Требования к широковещательным событиям

Следующие зависимости будут необходимы:

  • Pusher: pusher/pusher-php-server ~2.0
  • Redis: predis/predis ~1.0

Требования к очереди

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

Помечаем широковещательные события

Чтобы проинформировать Laravel о том, что заданное событие должно быть широковещательным, реализуйте интерфейс Illuminate\Contracts\Broadcasting\ShouldBroadcast в классе события. Интерфейс ShouldBroadcast требует реализации одного метода: PHPbroadcastOn(). Метод PHPbroadcastOn() должен возвращать массив «channel» имён, для которого событие должно быть широковещательным:

PHP
<?php

namespace App\Events;

use 
App\User;
use 
App\Events\Event;
use 
Illuminate\Queue\SerializesModels;
use 
Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class 
ServerCreated extends Event implements ShouldBroadcast
{
  use 
SerializesModels;

  public 
$user;

  
/**
   * Создание нового экземпляра события.
   *
   * @return void
   */
  
public function __construct(User $user)
  {
    
$this->user $user;
  }

  
/**
   * Получение каналов, для которых событие должно быть широковещательным.
   *
   * @return array
   */
  
public function broadcastOn()
  {
    return [
'user.'.$this->user->id];
  }
}

Теперь вам нужно только запустить событие, как вы это обычно делали. Как только событие было запущено, обработчик очереди автоматически передаст широковещательное событие по вашему указанному широковещательному драйверу.

+ 5.1 5.0

добавлено в 5.1 () 5.0 ()

Переписываем имена широковещательных событий

По умолчанию широковещательное имя события будет полностью определенным именем класса события. Используя класс в качестве примера выше, широковещательное событие было бы App\Events\ServerCreated. Вы можете определить имя широковещательного события, как вам будет удобнее, используя метод PHPbroadcastAs():

PHP
/**
 * Получить имя широковещательного события.
 *
 * @return string
 */
public function broadcastAs()
{
    return 
'app.server-created';
}
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

Широковещательные данные

Когда событие широковещательное, все его public свойства автоматически сериализированы и передаются вместе с событием, что позволяет вам получить доступ к любым из его общедоступных данных из JavaScript приложения. Например, если у вашего события есть единственное общедоступное свойство $user, которое содержит Eloquent модель, широковещательные данные будут выглядеть так:

{
  "user": {
    "id": 1,
    "name": "Jonathan Banks"
    ...
  }
}

Однако, если вы хотите иметь еще более тщательный контроль над своими широковещательными данными, вы можете добавить к своему событию метод PHPbroadcastWith(). Этот метод должен возвращать массив данных, которые вы хотите передать с событием:

PHP
/**
 * Получить данные для передачи.
 *
 * @return array
 */
public function broadcastWith()
{
    return [
'user' => $this->user->id];
}
+ 5.2

добавлено в 5.2 ()

Настройка широковещательных событий

Настройка имени события

По умолчанию имя широковещательного события — это полное имя класса этого события. Например, если имя класса App\Events\ServerCreated, то событие будет App\Events\ServerCreated. Имя можно изменить, определив метод PHPbroadcastAs() в классе события:

PHP
/**
 * Получение имени широковещательного события.
 *
 * @return string
 */
public function broadcastAs()
{
  return 
'app.server-created';
}

Настройка очереди

По умолчанию каждое широковещательное событие помещается в очередь по умолчанию для подключения по умолчанию в вашем файле настроек queue.php. Можно изменить очередь для вещания событий, добавив метод PHPonQueue() в класс события. Этот метод должен возвращать имя нужной очереди:

PHP
/**
 * Задание имени очереди для размещения событий.
 *
 * @return string
 */
public function onQueue()
{
  return 
'your-queue-name';
}
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

Использование широковещательных событий

Pusher

Вы можете удобно использовать широковещательную передачу событий, используя драйвер Pusher, используя Pusher SDK JavaScript. Например, давайте используем событие App\Events\ServerCreated из наших предыдущих примеров:

PHP
this.pusher = new Pusher('pusher-key');

this.pusherChannel this.pusher.subscribe('user.' USER_ID);

this.pusherChannel.bind('App\\Events\\ServerCreated', function(message) {
  
console.log(message.user);
});

Redis

Если вы будете использовать Redis, то вы должны будете написать свой собственный Redis потребитель типа издатель-подписчик, чтобы получать сообщения и широковещательно передавать их, используя websocket технологию на ваш выбор. Например, вы можете воспользоваться популярной библиотекой Socket.io, которая написана на Node.

Используя библиотеки Node socket.io и ioredis, вы можете быстро написать broadcaster событий, чтобы публиковать все события, которые широковещаются вашим приложением Laravel:

PHP
var app = require('http').createServer(handler);
var 
io = require('socket.io')(app);

var 
Redis = require('ioredis');
var 
redis = new Redis();

app.listen(6001, function() {
  
console.log('Server is running!');
});

function 
handler(reqres) {
  
res.writeHead(200);
  
res.end('');
}

io.on('connection', function(socket) {
  
//
});

redis.psubscribe('*', function(errcount) {
  
//
});

redis.on('pmessage', function(subscribedchannelmessage) {
  
message JSON.parse(message);
  
io.emit(channel ':' message.eventmessage.data);
});

Подписчики событий

Написание подписчиков событий

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

PHP
<?php

namespace App\Listeners;

class 
UserEventSubscriber
{
  
/**
   * Обработка события входа пользователя в систему.
   */
  
public function onUserLogin($event) {}

  
/**
   * Обработка события выхода пользователя из системы.
   */
  
public function onUserLogout($event) {}

  
/**
   * Регистрация слушателей для подписки.
   *
   * @param  Illuminate\Events\Dispatcher  $events
   */
  
public function subscribe($events)
  {
    
$events->listen(
      
'Illuminate\Auth\Events\Login',
      
'App\Listeners\UserEventSubscriber@onUserLogin'
    
);

    
$events->listen(
      
'Illuminate\Auth\Events\Logout',
      
'App\Listeners\UserEventSubscriber@onUserLogout'
    
);
  }

}

Регистрация подписчика события

После написания подписчика, вы можете зарегистрировать его в диспетчере события. Вы можете зарегистрировать подписчиков, используя свойство $subscribe в EventServiceProvider. Например, давайте добавим UserEventSubscriber.

PHP
<?php

namespace App\Providers;

//для версии 5.2 и ранее:
//use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class 
EventServiceProvider extends ServiceProvider
{
  
/**
   * Привязки слушателя события для приложения.
   *
   * @var array
   */
  
protected $listen = [
    
//
  
];

  
/**
   * Классы подписчиков для регистрации.
   *
   * @var array
   */
  
protected $subscribe = [
    
'App\Listeners\UserEventSubscriber',
  ];
}
+ 5.1 5.0

добавлено в 5.1 () 5.0 ()

События фреймворка

Laravel предоставляет множество «базовых» событий для действий, выполняемых фреймворком. Вы можете подписаться на них таким же образом, как вы подписываетесь на свои собственные события:

Событие Параметр(ы)
artisan.start$application
auth.attempt$credentials, $remember, $login
auth.login$user, $remember
auth.logout$user
cache.missed$key
cache.hit$key, $value
cache.write$key, $value, $minutes
cache.delete$key
connection.{name}.beganTransaction$connection
connection.{name}.committed$connection
connection.{name}.rollingBack$connection
illuminate.query$query, $bindings, $time, $connectionName
illuminate.queue.after$connection, $job, $data
illuminate.queue.failed$connection, $job, $data
illuminate.queue.stoppingnull
mailer.sending$message
router.matched$route, $request
{view name}$view
{view name}$view

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.