转载

基于Pusher驱动的Laravel事件广播(上)

说明:本文主要来源于 Building Real-Time Laravel Apps with Pusher 。

本文主要介绍使用Pusher包来开发带有实时通信功能的Laravel APP,整个教程只需要两个小时就能顺利走一遍。同时,作者会将开发过程中的一些截图和代码黏上去,提高阅读效率。

1. 教程相关

本教程所需条件:

  • 已经安装composer

  • 基本了解PHP

  • 基本了解Laravel

  • 基本了解jQuery

  • 有一个github账户

备注:Laravel是一个流行的PHP全栈框架,composer是一个PHP包管理器,jQuery是一个操作DOM树的JavaScript框架。如果有不了解的,可以在看教程前花半个小时谷歌下这些基本内容比较好。被墙了咋办,去github上搜lantern,你懂得。

1.1 Pusher是什么?

基于Pusher驱动的Laravel事件广播(上)

Pusher是客户端和服务器之间的实时中间层,通过WebSocket或HTTP来和客户端实现持久链接,这样服务端可以实时向客户端发送数据。总之,就是一个实现持久链接的包。

1.2 Pusher用途

(一) 通知(Notification)/信号(Signal)

通知是最简单的示例,也最经常用到。信号也可看作是通知的一种展现形式,只不过信号没有UI而已。

(二) Activity StreamsActivity Streams(feeds)是社交网络的核心。如微信朋友圈的点赞和评论,A可以实时看到B的点赞,B可以实时看到A的评论。

(三) 实时数据可视化如在dashboard数据面板中实时显示投票数,或者实时显示天气情况等等。

(四) 聊天

聊天信息的实时显示,如微信。

等等。具体可看 Pusher Use Cases

2. Pusher主要内容
这部分内容主要包括注册Pusher账号,在PHP程序中注册Pusher的ID和密钥,把Pusher的PHP包和JavaScript包集成进Laravel,以及如何调试Pusher程序。

2.1 注册Pusher账号

注册Pusher账号:可以在这里注册: pusher 注册 ,注册账号主要是为了获得appid,secret和key这三个认证密钥,同时注册后进入个人页面后,可以使用Pusher的Pusher Debug Console来查看接口调用情况。可以用github账号来注册登录的。

注册成功后进入个人后台面板,可以新建个应用程序名称,会有该新建程序的密钥,同时右边第二个tab还有个debug console,用来调试查看接口调用情况,等会会用到:

基于Pusher驱动的Laravel事件广播(上)

2.2 Laravel程序安装
先全局安装composer:

    curl -sS https://getcomposer.org/installer | php     mv composer.phar /usr/local/bin/composer

新建一个空文件夹,在文件夹下,再使用composer安装Laravel项目:

composer create-project laravel/laravel mylaravelapp --prefer-dist

2.3 配置Pusher认证密钥
在项目根目录的.env文件中加入密钥,把刚刚获得的密钥换成你自己的就行,.env文件是Laravel项目配置文件:

PUSHER_APP_ID=YOUR_APP_ID PUSHER_KEY=YOUR_APP_KEY PUSHER_SECRET=YOUR_APP_SECRET

然后,把Pusher集成到Laravel的后端,有两种方式:使用Laravel Pusher Bridge;使用Laravel Event Broadcaster。

2.4 Laravel Pusher Bridge
在 PHP包资源库 中查找 pusher ,安装:

composer require vinkla/pusher

安装完后注册下服务,service provider主要就是把刚刚下载的service(包)在Laravel容器中注册下,每一个service(包)都有对应的一个service privider:

Vinkla/Pusher/PusherServiceProvider::class,

并同时把这个包的配置文件复制到config文件夹下,config文件夹下多了一个pusher.php文件:

php artisan vendor:publish

在config/pusher.php文件中更新下配置文件:

'connections' => [      'main' => [         'auth_key' => env('PUSHER_KEY'),         'secret' => env('PUSHER_SECRET'),         'app_id' => env('PUSHER_APP_ID'),         'options' => [],         'host' => null,         'port' => null,         'timeout' => null,     ],

这里有一个安装bug:如果同时也在config/app.php中配置了Facade的话会报错,所以不用配置。可以使用/Illuminate/Support/Facades/App::make('pusher')来从Laravel的Container容器中取出Pusher服务。一般可以用Facade从容器中取出服务,但这个包不好使,有bug。
下面这句不用加在config/app.php中aliases[]数组中。

'Pusher' => Vinkla/Pusher/Facades/Pusher::class

配置并安装好这个包后就来检测下能不能使用:

 get('/bridge', function() {     $pusher = /Illuminate/Support/Facades/App::make('pusher');      $pusher->trigger( 'test-channel',                       'test-event',                        ['text' => 'I Love China!!!']                     );     return 'This is a Laravel Pusher Bridge Test!'; });

作者在MAMP PRO环境中,Apache端口是8888,在浏览器中输入 http://laravelpusher.app:8888/bridge 路由,正确返回 This is a Laravel Pusher Bridge Test! ,说明pusher已经触发。可以在Pusher Debug Console后台查看是否触发:

基于Pusher驱动的Laravel事件广播(上)

的确, it is working! 很简单是不是。

2.5 Laravel Event Broadcaster

Laravel5.1以后提供了Event Broadcaster功能,配置文件是config/broadcasting.php,并且默认驱动是pusher: 'default' => env('BROADCAST_DRIVER', 'pusher') ,如果不是可以在.env文件中添加BROADCAST_DRIVER=pusher。总之,不需要修改啥配置了。broadcasting.php中也是要读取pusher的密钥:

'connections' => [          'pusher' => [             'driver' => 'pusher',             'key' => env('PUSHER_KEY'),             'secret' => env('PUSHER_SECRET'),             'app_id' => env('PUSHER_APP_ID'),             'options' => [                 //             ],         ],         ...

既然事件广播,那就需要生成事件和对应的监听器,在app/Providers/EventServiceProvider.php中写入任何一个事件名称如SomeEvent,和对应的监听器如EventListener:

protected $listen = [         'App/Events/PusherEvent' => [             'App/Listeners/PusherEventListener',         ],     ];

然后在项目根目录生成事件和对应的监听器:

php artisan event:generate

Laravel中事件如果需要广播,必须实现IlluminateContractsBroadcastingShouldBroadcast接口,并且事件中public属性都会被序列化作被广播的数据,即public属性数据会被发送。同时,还需要在broadcastOn()函数中写入任意字符的广播频道:

class PusherEvent extends Event implements ShouldBroadcast {     use SerializesModels;      public $text, $id;     /**      * Create a new event instance.      *      * @return void      */     public function __construct($text, $id)     {         $this->text = $text;         $this->id   = $id;     }      /**      * Get the channels the event should be broadcast on.      *      * @return array      */     public function broadcastOn()     {         return ['laravel-broadcast-channel'];     } }

好,然后触发这个事件,为了简单,就直接在路由中触发:

Route::get('/broadcast', function () {     event(new /App/Events/PusherEvent('Great Wall is great ', '1'));     return 'This is a Laravel Broadcaster Test!'; });

在Pusher Debug Console中查看触发结果:

基于Pusher驱动的Laravel事件广播(上)

It is working!

其中'laravel-broadcast-channel'就是Channel属性,AppEventsPusherEvent是Event属性,PusherEvent的public属性是被广播的数据,为了检验只有public属性被广播:

class PusherEvent extends Event implements ShouldBroadcast {     use SerializesModels;      public $text, $id;     private $content;     protected $title;     /**      * Create a new event instance.      *      * @return void      */     public function __construct($text, $id, $content, $title)     {         $this->text    = $text;         $this->id      = $id;         $this->content = $content;         $this->title   = $title;     }      /**      * Get the channels the event should be broadcast on.      *      * @return array      */     public function broadcastOn()     {         return ['laravel-broadcast-channel'];     } }  //routes.php中 Route::get('/broadcast', function () {     event(new /App/Events/PusherEvent('This is a public attribute', '2', 'This is a private attribute', 'This is a protected attribute'));     return 'This is a Laravel Broadcaster Test, and private/protected attribute is not fired!'; });

重新触发查看Pusher Debug Console,的确只有public属性数据被广播:

基于Pusher驱动的Laravel事件广播(上)

2.6 Laravel Pusher Bridge vs Laravel Event Broadcaster

使用Laravel Pusher Bridge可以不必被Event Broadcaster的一些规则束缚,并且可以通过pusher实例来获取Pusher提供的其他服务如验证频道订阅,查询程序状态等等。不过使用Laravel Event Broadcaster可以实现模块解耦,当有其他的更好的push包时可以快速切换别的服务。可以选择适合的方法。

2.7 调试Pusher服务端集成包
本小节主要涵盖使用Laravel Pusher Bridge方法作为事件广播的调试。使用Pusher PHP包的Log模块并结合Laravel的Log模块进行调试:

use Illuminate/Support/Facades/App; use Illuminate/Support/Facades/Log;  class LaravelLoggerProxy{     public function log($msg)     {         Log::info($msg);     } }  class AppServiceProvider extends ServiceProvider {     /**      * Bootstrap any application services.      *      * @return void      */     public function boot()     {         $pusher = App::make('pusher');         $pusher->set_logger();     }     ...

作者在个人环境中,输入 http://laravelpusher.app:8888/bridge ,在storage/logs/laravel.log中会出现类似如下的调试信息,可以先清空下laravel.log文件再查看:

[2016-04-25 02:25:10] local.INFO: Pusher: ->trigger received string channel "test-channel". Converting to array.   [2016-04-25 02:25:10] local.INFO: Pusher: curl_init( http://api.pusherapp.com:80/apps/200664/events?auth_key=ae93fbeaff568a9223d3&auth_signature=ff8ce0b76038aea6613b4849ddda1b2bd0b14976738e8751264bf8f3cab3bc41&auth_timestamp=1461551110&auth_version=1.0&body_md5=bde7265f1c9da80ce0a3e0bde5886b5a )   [2016-04-25 02:25:10] local.INFO: Pusher: trigger POST: {"name":"test-event","data":"{/"text/":/"I Love China!!!/"}","channels":["test-channel"]}   [2016-04-25 02:25:11] local.INFO: Pusher: exec_curl response: Array (     [body] => {}     [status] => 200 )

调试信息可看到,使用pusher是往这个接口 http://api.pusherapp.com:80/apps/200664/events?auth_key=&auth_signature=&auth_timestamp=&auth_version=&body_md5= 发POST数据,发的数据主要是3个:频道channels(如:test-channel),事件event(如:test-event)和数据data(如:I love China)。最后返回响应,状态200,就表示发送成功了。如果输入路由 http://laravelpusher.app:8888/broadcast 则laravel.log中不打印调试消息。

有时间可以看下Laravel Debug Bar,就是一个供Laravel调试的包,地址: Laravel Debug Bar ,这大牛还写了个Laravel IDE Helper也非常好用: Laravel IDE Helper 。。强烈建议把这两个包安装到你的项目中,每一个新Laravel项目都可以安装下。。

2.8 使用Pusher JavaScript包

好,既然服务端可以工作正常了,那现在开始研究下客户端来接收事件触发时服务端发送来的数据。

可以新建一个view,或者直接使用已有的welcome.blade.php这个view,但先把这个文件的<link href=" https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">注销掉免得每次加载有些慢。在文件中写入代码:

<script src="//js.pusher.com/3.0/pusher.min.js"></script> <script> var pusher = new Pusher("{{env("PUSHER_KEY")}}") var channel = pusher.subscribe('test-channel'); channel.bind('test-event', function(data) {   console.log(data);   console.log(data.text); }); </script>

先加载pusher的js包,再利用pusher对象去订阅频道,再用频道绑定触发事件,闭包返回接收到的数据。这里订阅Laravel Pusher Bridge里写的test-channel频道,绑定test-event事件,打印text属性的数据,我们知道上文中我们写入了数据为['text' => 'I Love China!!!'],那客户端打印的数据应该是'I Love China!!!',看看是不是。在路由中输入 http://laravelpusher.app:8888/bridge 看看Pusher Debug Console发生什么:

基于Pusher驱动的Laravel事件广播(上)

然后新开一个标签页再输入路由看看console窗口打印信息:

基于Pusher驱动的Laravel事件广播(上) It is working!

可以多次刷新路由,在两个标签页面间切换看看打印的数据。A页面触发事件B页面能接收到数据;B页面触发事件A页面接收到数据。

2.9 调试Pusher JavaScript客户端
可以使用Pusher Debug Console控制面板查看触发情况,当然可以在客户端打印调试信息:

<script>             Pusher.log = function(msg) {                 console.log(msg);             };             var pusher = new Pusher("{{env("PUSHER_KEY")}}");             var channel = pusher.subscribe('test-channel');             ...

基于Pusher驱动的Laravel事件广播(上) 看打印信息知道,开始是connecting,然后连接成功connected,然后频道订阅成功subscription_succeeded,最后事件也被接收且数据也发送成功Event recd。

总结:上部分包括Pusher服务账号注册、Laravel实时APP安装、Pusher服务端的集成和调试和Pusher客户端的集成和调试。下部分将主要以示例来说明,包括:Real-Time Notification, Activity Stream, Chat。

原文  https://segmentfault.com/a/1190000004997982
正文到此结束
Loading...