说明:本文主要来源于 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是客户端和服务器之间的实时中间层,通过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,用来调试查看接口调用情况,等会会用到:
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后台查看是否触发:
的确, 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中查看触发结果:
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属性数据被广播:
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发生什么:
然后新开一个标签页再输入路由看看console窗口打印信息:
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'); ...
看打印信息知道,开始是connecting,然后连接成功connected,然后频道订阅成功subscription_succeeded,最后事件也被接收且数据也发送成功Event recd。
总结:上部分包括Pusher服务账号注册、Laravel实时APP安装、Pusher服务端的集成和调试和Pusher客户端的集成和调试。下部分将主要以示例来说明,包括:Real-Time Notification, Activity Stream, Chat。