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

События

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

  1. 1. Введение
  2. 2. Регистрация событий / слушателей
    1. 2.1. Генерация классов событий / слушателей
    2. 2.2. Регистрация событий вручную
  3. 3. Определение событий
  4. 4. Определение слушателей
    1. 4.1. Слушатели события в очереди
  5. 5. Запуск событий
  6. 6. Широковещательные события
    1. 6.1. Конфигурация
    2. 6.2. Помечаем широковещательные события
    3. 6.3. Широковещательные данные
    4. 6.4. Использование широковещательных событий
  7. 7. Подписчики событий
  8. 8. События фреймворка
Этот перевод актуален для англоязычной документации на (ветка 5.1) и (ветка 5.0). Опечатка? Выдели и нажми Ctrl+Enter.

Введение

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

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

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

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

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

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

shphp artisan event:generate

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

Как правило, события должны регистрироваться через массив $listen EventServiceProvider. Однако, также вы можете регистрировать события вручную с обработчиком событий, используя либо фасад 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
$events->listen('event.*', function (array $data) {
  
//
});

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

Класс события — это просто контейнер данных, содержащий информацию, которая относится к событию. Например, предположим, что наше сгенерированное событие 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() вы можете выполнять любую логику, необходимую для ответа на событие.

PHP
<?php

namespace App\Listeners;

use 
App\Events\PodcastWasPurchased;
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() вашего слушателя.

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

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

PHP
<?php

namespace App\Listeners;

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

class 
EmailPurchaseConfirmation implements ShouldQueue
{
  
//
}

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

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

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

PHP
<?php

namespace App\Listeners;

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

class 
EmailPurchaseConfirmation implements ShouldQueue
{
  use 
InteractsWithQueue;

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

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

Чтобы запустить событие, вы можете использовать фасад 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];
  }
}

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

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

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

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

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

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

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

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

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

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

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(), в который будет передан экземпляр диспетчера события:

PHP
<?php

namespace App\Listeners;

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

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

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

    
$events->listen(
      
'App\Events\UserLoggedOut',
      
'App\Listeners\UserEventListener@onUserLogout'
    
);
  }

}

Регистрация слушателей для подписки

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

PHP
<?php

namespace App\Providers;

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\UserEventListener',
  ];
}

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

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

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

Разметка: ? ?

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