laravel 基础教程 —— 事件

事件

简介

laravel
的风波提供了一种简易的观望者落成。它同意你在动用中展开订阅和监听事件。事件类一般都是储存在
app/Events 目录中,而他们的监听者都是储存在 app/Listeners 目录中。

挂号事件/监听者

EventServiceProvider 提供了一个挂号所有事件监听者的便民的场面。它的
listen
属性包罗了一个具有事件(keys)以及她们的监听者(values)所结合的数组。当然,你可以在这些数组中充分任何你必要的轩然大波。比如,让我们添加
PodcastWasPurchased 事件:

/**
 * The event listener mappiings for the application.
 *
 * @var array
 */
 protected $listen = [
   'App\Events\PodcastWasPurchased' => [
     'App\Listeners\EmailPurchaseConfirmation',
   ],
 ],

转变事件/监听者类

当然,每便都手动的去创制一个事变文件和一个监听者文件是很麻烦的业务,所以,你能够在
EventServiceProvider 中添加事变和监听者然后接纳 event:generate
命令来自动生成。那么些命令会生成 EventServiceProvider
中的所有列出的风波和监听者,当然,已经存在的轩然大波和监听者不会另行生成:

php artisan event:generate

手动的注册事件

不足为奇,事件应该被注册在 EventServiceProvider$listen
数组中,事实上,你可以行使 Event 假面的风浪分发器恐怕一个
Illuminate\Contracts\Events\Dispatcher 的兑现来手动注册事件:

/**
 * Register any other events for your application
 *
 * @param \Illuminate\Contracts\Events\Dispatcher $events
 * @return void
 */
 public function boot(DispatcherContract $events)
 {
   parent::boot($events);

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

事件监听通配符

你可以在注册监听器的时候利用 *
来作为通配符。那允许你来在同一个监听器中监听种种事变。通配符监听器接收整个事件数量数组作为第二个参数:

$events->listen('event.*', function (array $data) {
  // 
});

概念事件

一个风浪类只是简单的数量存储器,它应有拥有事件有关的新闻.比如,让大家如若大家转变的
PodcastWasPurchased 事件应该吸纳一个 Eloquent OKugaM 对象:

<?php

namespace App\Events;

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

class PodcastWasPurchased extends Event
{
  use SerializesModels;

  public $podcast;

  /**
   * Create a new event instance.
   *
   * @param Podcast $podcast
   * @return void
   */
   public function __construct(Podcast $podcast)
   {
     $this->podcast = $podcast;
   }
}

就像您所观望的,那些事件类并不曾包蕴哪些业务逻辑。它只是简短的含有了一个被购买的
Podcast 对象。SerializesModels trait 被用来系列化 Eloquent
模型,如果事件目的是采纳 PHP 的 serialize 方法被举行体系化,那么
SerializesModels 就会优雅的将其内部的 Eloquent 对象序列化。

概念监听者

随后,让大家来看一下对准大家地方举例的风浪的监听者。事件监听者会在其
handle 方法中收取事件的实例。event:generate 命令会自动的在 handle
方法中引入其对应的轩然大波的项目指示。你可以在 handle
方法中来提供对事件的响应逻辑:

<?php

namespace App\Listeners;

use App\Events\PodcastWasPurchased;

class EmailPurchaseConfirmation
{
  /**
   * Create the event listener.
   *
   * @return void
   */
   public function __construct()
   {
     //
   }

   /**
    * Handle the event.
    *
    * @param PodcastWasPurchased $event
    * @return void
    */
    public function handle(PodcastWasPurchased $event)
    {
      // Access the podcast using $event->podcast...
    }
}

你的事件监听者也可以在构造函数中开展项目提醒来注入重视。所有的风云监听器都是透过
laravel 的劳务容器解析的。所以,它们的看重品质够被活动的流入:

use Illuminate\Contracts\Mail\Mailer;

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

停下传递事件

有时,你或然希望为止传递事件到两次三番的监听者中。你可以在监听者的
handle 方法中回到 false,那样持续的监听者将不再举办事件的响应。

监听者队列化

亟待对事件监听者举办队列化?没有比那更简单的了。间接添加 ShouldeQueue
接口到监听者类中就可以了。通过 event:generate Artisan
命令生成的监听者已经在脚下的命名空间中添加了对那个接口的支撑,所以您霎时就足以动用:

<?php

namespace App\Listeners;

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

class EmailPurchaseConfirmation implements ShouldQueue
{
  //
}

似乎此简单!当事件触发时,事件分发器会利用 laravel
的行列系统对监听器进行机动的队列化调用。若是监听器队列化执行的历程中绝非越发出现,队列职责会自动的在监听器进程达成后进行删减。

手动的拜会队列

尽管您要求手动的走访底层队列职责的 deleterelease
方法。那么你就足以一向去行使它们。Illuminate\Queue\InteractsWithQueue
trait 对暗中认可生成的监听器提供了拜访这一个措施的权能:

<?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 假面来进行事件的触及,你须求传递一个风云实例到 fire
方法中。fire 方法会分发事件到持有的监听器中:

<?php

namespace App\Http\Controllers;

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

class UserController extends Controller
{
  /**
   * Show the profile for the given user.
   *
   * @param int $userId
   * @param int $podcastId
   * @return Response
   */
  public function purchasePodcast($userId, $podcastId)
  {
    $podcast = Podcast::findOrFail($podcastId);

    // Purchase podcast logic...

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

其它,你仍能透过选用全局 event 协理函数来触发事件:

event( new PodcastWasPurchased($podcast));

广播事件

成千成万现代化的应用中,会选用 web sockets
来落到实处实时互动的用户接口。当有的数额在服务端变更时,一条音信会通过
websocket 连接来传递到客户端进行拍卖。

为了救助你打造那种类型的使用。laravel 使通过 websocket
连接举办广播事件变的卓殊不难。laravel
允许你广播事件来共享事件的称谓到您的服务端和客户端的 JavaScript 框架。

配置

有着的轩然大波广播配置选项都被储存在 config/broadcasting.php
配置文件中。laravel
协理三种开箱即用的播音驱动:PusherRedis
log
驱动来提供当地开发和调试。在那些布局文件中隐含了每一个驱动的配备示范。

播音先决条件

事件广播要求以下倚重:

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

队列化先决条件

在举行事件广播之前,你要求先配备好队列监听器。所有的播报都以因而队列职分来异步执行的,那样应用响应就不会惨遭震慑。

对事件展开播报

你必要贯彻 Illuminate\Contracts\Broadcasting\ShouldBroadcast
接口在事变类中,以布告 laravel 所给定的风云要求被广播。ShouldBroadcast
接口只须求你完成一个十足的法门:broadcastOn.该办法应该回到一个事变应该被广播的通道名称:

<?php

namespace App\Events;

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

class ServerCreated extends Event implements ShouldBroadcast
{
  use SerializesModels;

  public $user;

  /**
   * Create a new event instance.
   *
   * @return void
   */
  public function __construct(User $user)
  {
    $this->user = $user;
  }

  /**
   * Get the channels the event should be broadcast on.
   *
   * @return array
   */
   public function broadcastOn()
   {
     return ['user.' . $this->user->id];
   }
}

接下来,你只须要像寻常那样去接触事件就足以了。一旦事件被触发,队列职责会活动的广播事件到你指定的播音驱动中。

播音数据

当一个事件被广播时,事件类的有着 public
属性都会被系列化并作为广播的负荷,允许你的前端 JavaScript
应用来拜会具有的怒放性质。比如,如若事件类中唯有一个盛开的 $user
属性,该属性包罗了一个 Eloquent 模型,那么广播的载重将会像这么:

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

实质上,你可以经过在事件中添加 broadcastWith
方法来对播音载荷拥有越多的操纵。该办法应该回到一个数组:

/**
 * Get the data to broadcast.
 *
 * @return array
 */
 public function broadcastWith()
 {
   return ['user' => $this->user->id];
 }

定制化事件广播

定制事件名称

暗中认同的,广播事件的名号会利用事件类的姓名。比如,假诺事件的类名是
App\Events\ServerCreated,那么广播事件的称谓就是
App\Events\ServerCreated。你可以经过定义 broadcastAs
方法来自定义广播事件的称号:

/**
 * Get the broadcast event name
 *
 * @return string
 */
 public function broadcastAs()
 {
   return 'app.server-created';
 }

定制化队列

默许的,所有的风云广播都以因而 queue.php
配置文件中所指定的私行认同队列配置来进行的。你可以因此在事变广播类中添加一个
onQueue
方法来指定所选拔的体系。该格局应该回到一个您所企望利用的队列的称呼:

/**
 * Set the name of the queue the event should be placed on.
 *
 * @return string
 */
 public function onQueue()
 {
   return 'your-queue-name';
 }

对接广播事件

Pusher

您可以使用 Pusher
驱动的 JavaScript SDK来轻松的连通广播事件。比如,让大家开销前边例子中的
App\Events\ServerCreated 事件:

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
技术来进展事件的广播。比如,你可以选用选取基于 Node 受欢迎的
Socket.io 类库。

您可以使用 socket.ioioredisPHP, Node
类库来很快的编撰事件广播员来发表所有的选取事件:

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(req, res) {
  res.writeHead(200);
  res.end('');
}

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

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

redis.on('pmessage', function (subscrbed, channel, message) {
  message = JSON.parse(message);
  io.emit(channel + ':' + message.event, message.data);
});

事件订阅

事件订阅允许一个类在其内部订阅多个事件。这允许你在同一个文件中对三个事件开展拍卖。订阅者应该定义
subscribe 方法。该方法会被传送一个风浪分发器实例:

<?php

namespace App\Listeners;

class UserEventListener
{
  /**
   * Handle user login events.
   */
   public function onUserLogin($event) {}

   /**
    * Handle user logout events.
    */
    public function onUserLogout($event) {}

    /**
     * Register the listeners for the subscriber.
     *
     * @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'
        );
     }
}

登记一个轩然大波订阅者

当你的订阅者被定义完结之后,它应当在事变分发器中开展挂号。你可以运用
EventServieProvider$subscribe
属性来注册订阅者。比如,让大家来添加一个 UserEventListener:

<?php

namespace App\Providers;

use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
  /**
   * The event listener mapping for the application.
   *
   * @var array
   */
   protected $listen = [
     //
   ];

   /**
    * The subscriber classes to register.
    *
    * @var array
    */
    protected $subscribe = [
      'App\Listeners\UserEventListener',
    ];
}

相关文章