kibana 喊话
Laravel is undoubtedly a very powerful framework with a lot of batteries included. One of the reasons I love laravel is the fact that it is built on events.
Laravel无疑是一个非常强大的框架,其中包含很多电池。 我喜欢laravel的原因之一是事实,它基于事件。
An event is an action or occurrence recognized by a program that may be handled by the program. Some examples of events in Laravel would be:
事件是程序可以识别的动作或事件,可以由程序处理。 Laravel事件的一些示例是:
The reason we use events is because they allow us to separate application concerns and creates a mechanism for us to hook into actions in our application. When an event is fired, the event does not need to know anything about its implementation, all the event needs to know is that an action is performed, the event is triggered, the event sends some data to a listener or subscriber somewhere that has to deal with it.
我们使用事件的原因是因为它们使我们能够分离应用程序的关注点,并为我们创建了一种机制,使我们可以挂接到应用程序中的动作上。 触发事件后,该事件无需了解任何有关其实现的信息,所有事件需要知道的是执行了某项操作,触发了该事件,该事件将一些数据发送到某个地方的侦听器或订阅者处理它。
To show off how an app would start to look without events, we would do something like the following:
为了展示应用程序在没有事件的情况下的外观,我们将执行以下操作:
Route::get('signup', function() {
// create the new user
$user = User::create($userData);
// a user is created, do things!
// send the user a confirmation email
// set up that users account
// email them introductory information
// do more stuff
});
We can see how the list could start getting a little long. We can separate this out into an event so that a lot of the logic is separated from the event itself.
我们可以看到列表开始变长了。 我们可以将其分离为一个事件,以便将许多逻辑与事件本身分离开。
Another reason we use events is to speed up application data processing.
我们使用事件的另一个原因是加快应用程序数据处理。
NOTE: If you are already familiar with Pub Sub, events should not be a new concept.
注意:如果您已经熟悉Pub Sub ,那么事件应该不是一个新概念。
Still using the social blogging application, when a user creates a blog post, we might have a checklist of things to do like:
仍然使用社交博客应用程序,当用户创建博客文章时,我们可能会提供一份清单,其中包括:
Lining actions like this can slow down your application and events can be used remove this bottleneck.
这样的衬里动作可能会使您的应用程序变慢,并且可以使用事件来消除此瓶颈。
Laravel also triggers a lot of system events, for example:
Laravel还触发许多系统事件,例如:
These are just some events fired by laravel.
这些只是laravel触发的一些事件。
To generate an event in Laravel, we simply use good old artisan
要在Laravel中生成事件,我们只需要聘用优秀的老工匠
php artisan make:event ActionDone
This creates a class with the name ActionDone
in app/Events
directory, and it should look like this:
这将在app/Events
目录中创建一个名称为ActionDone
的类,并且应如下所示:
<?php namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class ActionDone extends Event {
use SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should be broadcast on.
*
* @return array
*/
public function broadcastOn()
{
return [];
}
}
Event creation is very simple and requires very little setup.
事件创建非常简单,只需很少的设置。
After an event is triggered, the application needs to know how to deal with the event and for that we need a Listener. To generate a listener in Laravel, we can simply use artisan:
触发事件后,应用程序需要知道如何处理事件,为此,我们需要一个侦听器。 要在Laravel中生成一个侦听器,我们可以简单地使用artisan:
php artisan make:listener ThingToDoAfterEventWasFired --event="ActionDone"
The command to generate a listener for the event takes in a required --event
flag with the name of the event to listen for. The above command creates a class named ThingToDoAfterEventWasFired
in app/Listeners
, and contains;
生成事件侦听器的命令带有一个必需的--event
标志,其中包含要侦听的事件的名称。 上面的命令在app/Listeners
创建一个名为ThingToDoAfterEventWasFired
的类,并包含;
<?php namespace App\Listeners;
use App\Events\ActionDone;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class ThingToDoAfterEventWasFired {
/**
* Create the event listener.
*
* @return void
*/
public function __construct() { // }
/**
* Handle the event.
*
* @param ActionDone $event
* @return void
*/
public function handle(ActionDone $event)
{
//
}
}
In the event listener class, the handle method is programmatically triggered by Laravel and it type-hints the triggered event's class.
在事件侦听器类中,handle方法由Laravel以编程方式触发,并类型化提示所触发事件的类。
Before we go on firing events here and there, Laravel's command bus needs to know about the events and their listeners, and how to handle them.
在我们四处触发事件之前,Laravel的命令总线需要了解事件及其侦听器以及如何处理它们。
To register the events, we navigate to app/Providers/EventServiceProvider.php
, we find the protected listen property on the EventServiceProvider
class and:
要注册事件,我们导航到app/Providers/EventServiceProvider.php
,在EventServiceProvider
类上找到受保护的监听属性,然后:
protected $listen = [
'App\Events\ActionDone' => [
'App\Listeners\ThingToDoAfterEventWasFired',
],
];
That's all we need to do to let the command bus know about an event and it's listeners. Notice that there is an array of listeners, meaning the event can have multiple subscribers.
我们要做的就是让命令总线知道一个事件及其侦听器。 请注意,这里有一组侦听器,这意味着事件可以有多个订阅者。
To have an event fire off multiple listeners, just add to that array:
要使一个事件触发多个侦听器,只需将其添加到该数组中:
protected $listen = [
'App\Events\ActionDone' => [
'App\Listeners\ThingToDoAfterEventWasFired',
'App\Listeners\OtherThingToDoAfterEventWasFired',
'App\Listeners\AnotherThingToDoAfterEventWasFired',
],
];
Event subscribers are classes that may subscribe to multiple events from within the class itself, allowing you to define several event handlers within a single class. In the above example, we explicitly name the listeners for an event inside the EventServiceProvider.php
file. We'll define events and listeners in a new UserEventListener.php
file.
事件订阅者是可以从该类本身中预订多个事件的类,使您可以在单个类中定义多个事件处理程序。 在上面的示例中,我们在EventServiceProvider.php
文件中显式命名事件的侦听器。 我们将在新的UserEventListener.php
文件中定义事件和侦听器。
Subscribers should define a subscribe method, which will be passed an event dispatcher instance:
订阅服务器应定义一个订阅方法,该方法将传递给事件分配器实例:
<?php namespace App\Listeners;
class UserEventListener {
/**
* Handle user login events.
*/
public function onUserLogin($event) {}
/**
* Handle user logout events.
*/
public function onUserLogout($event) {}
public function subscribe($events)
{
$events->listen(
'App\Events\UserLoggedIn',
'App\Listeners\UserEventListener@onUserLogin'
);
$events->listen(
'App\Events\UserLoggedOut',
'App\Listeners\UserEventListener@onUserLogout'
);
}
}
To register an event subscriber, go back to the EventServiceProvider
class, and in the subscribe property add the subscriber class:
要注册事件订阅者,请返回EventServiceProvider
类,然后在EventServiceProvider
属性中添加订阅者类:
protected $subscribe = [
'App\Listeners\UserEventListener',
];
Now all the events and listeners created in the UserEventListener
will work.
现在,在UserEventListener
创建的所有事件和侦听器都将起作用。
To fire events, we can use the Event
Facade to fire the event
要触发事件,我们可以使用Event
外观来触发事件
use Event;
use App\Events\ActionDone;
...
Event::fire(new ActionDone());
or we can use an event
helper method to fire the event
或者我们可以使用event
助手方法来触发事件
use App\Events\ActionDone;
...
event(new ActionDone());
To pass data to the listeners, we can simply use the event class as a DTO.
要将数据传递给侦听器,我们可以简单地将事件类用作DTO 。
Sometimes, we don't want the events/listeners to hold up our application's processing. For example, we wouldn't want a user to have to wait for their new user signup email to get emailed to them while they send the request to create their new account.
有时,我们不希望事件/侦听器阻止应用程序的处理。 例如,我们不希望用户在发送创建新帐户的请求时,必须等待其新用户注册电子邮件发送给他们。
We can add event listeners to our application queue and it would be handled by whatever queue driver you specify. This would not hold up our app processing. To do this we simply have the Listener class implement Illuminate\Contracts\Queue\ShouldQueue
.
我们可以将事件侦听器添加到我们的应用程序队列中,并且可以通过您指定的任何队列驱动程序进行处理。 这不会阻止我们的应用程序处理。 为此,我们只需让Listener类实现Illuminate\Contracts\Queue\ShouldQueue
。
<?php namespace App\Listeners;
use App\Events\ActionDone;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class ThingToDoAfterEventWasFired implements ShouldQueue { /*...*/ }
In many modern web applications, WebSockets are used to implement real-time, live-updating user interfaces. When some data is updated on the server, a message is typically sent over a WebSocket connection to be handled by the client.
在许多现代的Web应用程序中,WebSocket用于实现实时,实时更新的用户界面。 在服务器上更新某些数据时,通常会通过WebSocket连接发送一条消息,以由客户端处理。
To make an event broadcastable, you make the event class implement the Illuminate\Contracts\Queue\ShouldBroadcast
要使事件可广播,请使事件类实现Illuminate\Contracts\Queue\ShouldBroadcast
<?php namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class ActionDone extends Event implements ShouldBroadcast { /*...*/ }
The ShouldBroadcast
interface requires the event class to implement a broadcastOn
method which returns an array of channels the event should broadcast on.
ShouldBroadcast
接口要求事件类实现一个broadcastOn
方法,该方法返回事件应在其上广播的频道数组。
public function broadcastOn()
{
return ['action-did-occur'];
}
By default, Laravel serializes the event's public properties and sends it as JSON to the client. If you want more control over what is sent to the client you can add a broadcastWith
method to the event class and return the data to be converted into JSON.
默认情况下,Laravel序列化事件的公共属性,并将其作为JSON发送给客户端。 如果要对发送给客户端的内容进行更多控制,则可以向事件类添加broadcastWith
方法,然后返回要转换为JSON的数据。
public function broadcastWith()
{
return [
'user' => [
'name' => 'Klark Cent',
'age' => 30,
'planet' => 'Crypton',
'abilities' => 'Bashing'
]
];
}
Currently laravel has only two drivers(pusher and socket.io) to help with data consumption on the client. For the scope of this article we would be using pusher.
目前,laravel仅具有两个驱动程序( pusher和socket.io )来帮助减少客户端上的数据消耗。 对于本文的范围,我们将使用pusher。
Pusher is a WebSocket as a service, you send a request from your application to the service, and pusher broadcasts the message on all clients.
Pusher是作为服务的WebSocket,将请求从应用程序发送到服务,然后Pusher在所有客户端上广播消息。
To consume data on the client using pusher simply do this:
要使用pusher在客户端上使用数据,只需执行以下操作:
var pusher = new Pusher('pusher-key');
var channel = pusher.subscribe('action-did-occur');
channel.bind('App\Events\ActionDone', function(data) {
console.log(data);
});
NOTE: you need pusher's javascript SDK on the page.
注意 :您需要在页面上使用pusher的javascript SDK。
<script src="//js.pusher.com/2.2/pusher.min.js"></script>
You also need pusher's php sdk which is available via composer
您还需要可通过composer获得的pusher的php sdk
composer require pusher/pusher-php-server:~2.0
The demo application is a simple shoutbox, users fill in a form with their twitter handle, email address and what they would like to shout out.
该演示应用程序是一个简单的喊话框,用户使用其Twitter句柄,电子邮件地址以及他们想要喊出的内容填写表格。
Configure your .env
file, mine looks like this:
配置您的.env
文件,我的看起来像这样:
APP_ENV=local
APP_DEBUG=true
APP_KEY=ByuBK280rnHzE6DbC57byMzjVEvH4MeM
DB_HOST=localhost
DB_DATABASE=scotchbox
DB_USERNAME=root
DB_PASSWORD=password
PUSHER_KEY=69e9a2bc295b6ca2c212
PUSHER_SECRET=a2b80fa2b04c4fa0ccf0
PUSHER_APP_ID=140801
For more info on the .env
file and what it does, read the following: Understanding Laravel Environment Variables
有关.env
文件及其作用的更多信息,请阅读以下内容: 了解Laravel环境变量
Pusher is a great service that makes real-time components of our application effortless. They are a paid service but there is a free sandbox option (20 max connections, 100k messages per day) which should be enough for a small application or just for development. Go ahead and create an account on Pusher to get your credentials.
Pusher是一项出色的服务,它使我们应用程序的实时组件毫不费力。 它们是一项付费服务,但有一个免费的沙箱选项(最大20个连接,每天10万条消息),对于小型应用程序或仅用于开发的应用程序就足够了。 继续并在Pusher上创建一个帐户以获取您的凭据。
Let's get our database ready to hold our shoutouts
. We're going to need to create the shoutouts
table using a migration and an Eloquent model.
让我们准备好数据库来举行shoutouts
。 我们将需要使用迁移和Eloquent模型创建shoutouts
表。
Run the following from the command line in the root of your project:
从项目根目录的命令行运行以下命令:
php artisan make:migration create_shoutouts_table --create=shoutouts && php artisan make:model Models/Shoutout
The migration created by artisan (database/migrations/create_shoutouts_table.php
) contains:
工匠创建的迁移( database/migrations/create_shoutouts_table.php
)包含:
$table->increments('id');
$table->string('handle');
$table->string('email');
$table->text('content');
$table->timestamps();
The model should have protected fillable
and table
properties
模型应具有受保护的fillable
属性和table
属性
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'shoutouts';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['handle', 'email', 'content'];
Next we will setup routing and move on to creating our controller. In our app\Http\routes.php
file, we will create a resource route.
接下来,我们将设置路由并继续创建控制器。 在我们的app\Http\routes.php
文件中,我们将创建一个资源路由 。
Route::resource('shoutouts', 'SiteController');
Now that we have the routes mapped out, let's create the SiteController
using artisan.
现在我们已经SiteController
了路由,让我们使用工匠创建SiteController
。
php artisan make:controller SiteController
This resource route will automatically create some routes for our application including the ones needed for CRUD operations. To see the routes created, just use:
此资源路由将自动为我们的应用程序创建一些路由,包括CRUD操作所需的路由。 要查看创建的路线,只需使用:
php artisan route:list
The store
method in the newly created SiteController
will be the place where we handle creating and storing shoutboxes to the database. In our controller store
method let's add the following:
新创建的SiteController
的store
方法将是我们处理将shoutboxes创建和存储到数据库的地方。 在我们的控制器store
方法中,添加以下内容:
<?php namespace App\Http\Controllers;
...
use App\Models\Shoutbox;
public function store(Request $request) {
$validator = Validator::make($request->all(), Shoutout::$rules);
/**
* Try validating the request
* If validation failed
* Return the validator's errors with 422 HTTP status code
*/
if ($validator->fails())
{
return response($validator->messages(), 422);
}
$shoutout = Shoutout::create($request->only('email', 'handle', 'content'));
// fire ShoutoutAdded event if shoutout successfully added to database
event(new ShoutoutAdded($shoutout));
return response($shoutout, 201);
}
On the client side of things (JavaScript), connect to Pusher and listen to the App\Events\ShoutoutAdded
event.
在事物(JavaScript)的客户端上,连接到Pusher并侦听App\Events\ShoutoutAdded
事件。
var notifyUser = function (data) {
var data = data.shoutout;
if (! ('Notification' in window)) {
alert('Web Notification is not supported');
return;
}
Notification.requestPermission(function(permission){
var notification = new Notification('@'+ data.handle +' said:', {
body: data.content,
icon: document.getElementById('site_image').content
});
};
var loadPusher = function (){
Pusher.log = function(message) {
if (window.console && window.console.log) {
window.console.log(message);
}
};
var pusher = new Pusher(document.getElementById('pusher_key').content);
var channel = pusher.subscribe('shoutout-added');
channel.bind('App\\Events\\ShoutoutAdded', notifyUser);
};
The client listens for any broadcasted event and uses the Notification API to alert any user currently on the site. All we had to do to fire off our chain of events was use the following line in our controller:
客户端侦听任何广播的事件,并使用Notification API来警告站点上当前的任何用户。 要触发事件链,我们要做的就是在控制器中使用以下行:
// fire ShoutoutAdded event if shoutout successfully added to database
event(new ShoutoutAdded($shoutout));
You can see how we could separate out our application logic from the controller and into the event listener. That keeps our application lean and mean.
您将看到我们如何将应用程序逻辑与控制器分离,并分离为事件侦听器。 这使我们的应用程序精简而卑鄙。
Hopefully this helps you to see how easily events can be used and how they can streamline our applications.
希望这可以帮助您了解事件的使用方式以及事件如何简化我们的应用程序。
Events inform the application that an action occurred. They should not be misused, not every operation requires an event, but if they can move a lot of logic out of your more bloated controllers, then we'll be better organized.
事件通知应用程序发生了操作。 不应该滥用它们,不是每个操作都需要一个事件,但是如果它们可以将更多的逻辑移出更笨拙的控制器,那么我们将组织得更好。
翻译自: https://scotch.io/tutorials/create-a-real-time-shoutbox-with-laravel-events
kibana 喊话