上一篇:
Laravel 5 Event 事件 談到如何使用 Laravel 的 Event(事件),接著我們就要實作比較深入的 Event 功能 – Broadcasting(廣播)
此篇教學會以兩種 Laravel 5.2 所提供的 broadcaster 來當作範例
- Pusher
- Redis (草稿)
Pusher – 大致上的架構圖
讓我們以使用者發送訊息的角度來看這個架構圖
1.使用者透過 Ajax 發送訊息給 Laravel 執行 Event (Server 發送訊息) 與新增到 Database
2.Laravel 使用 Event 將資料以Http送給Pusher
3.Client 以 socket 監聽 Pusher 設定的某個 channel 並以添加訊息
安裝環境:
- Laravel 5.1+
- Predis – composer require predis/predis : “~1.1″
- Pusher – pusher/pusher-php-server : “~2.4.1″
你可能會疑問為什麼 Laravel 官方文件寫 套件 Pusher 只需 ~2.0,但這邊建議 ~2.4.1
套件連結:
這是一個大雷,因為我在 Pusher 2.0 的環境測試了許久,但我的 Pusher 帳戶卻一直沒辦法順利取得訊息
接著就發現 2.0 只會傳給 Pusher us 這個預設 api url,因此套件若您是用 US 則會正常,但你若部署在 eu 或是 ap1 則會出現
Unknown auth_key , code:400 的錯誤,因為他在 us cluster 中找尋不到你的 key
注意此連結程式碼 150行 ~ 158行,就是針對 boardcasting pusher cluster 去設定不同的 host,但 2.0 不支援
2.0 的套件中 options 參數的 cluster 填寫 ap1 要影響 Push $host 這個參數
套件必須在 2.4.1 以後才有支援,否則你得在 broadcasting.php 中多設定 host 參數
.env
| PUSHER_KEY=xxxxxxxxxxx |
| PUSHER_SECRET=xxxxxxxx |
| PUSHER_APP_ID=xxxxxx |
| PUSHER_CLUSTER=xxx |
app\Http\routes.php
| Route::any('send', 'HomeController@firingEvents'); |
| Route::get('get_pusher', 'HomeController@getPusherMessage'); |
取得不同路徑的呈現方式
config\broadcasting.php
| 'pusher' => [ |
| 'driver' => 'pusher', |
| 'key' => env('PUSHER_KEY'), |
| 'secret' => env('PUSHER_SECRET'), |
| 'app_id' => env('PUSHER_APP_ID'), |
| 'options' => [ |
| 'host' => 'api-ap1.pusher.com', // if pusher/pusher-php-server < 2.4.1. |
| 'cluster' => 'ap1' // require: pusher/pusher-php-server: ~2.4.1 |
| ], |
| ], |
broadcasting.php 這邊先設置 pusher driver
別忘了將 default 調整成 pusher
| 'default' => env('BROADCAST_DRIVER', 'pusher'), |
app\Controllers\HomeController.php
| |
| |
| namespace App\Http\Controllers; |
| |
| use App\Events\SendMessage; |
| use Illuminate\Http\Request; |
| |
| use App\Http\Requests; |
| |
| class HomeController extends Controller |
| { |
| public function firingEvents(Request $request) |
| { |
| $username = $request->get('username'); |
| $message = $request->get('message'); |
| $user = [ |
| 'id' => 10001, |
| 'username' => $username, |
| ]; |
| event(new SendMessage($user, $message)); |
| return 'message sent'; |
| } |
| |
| public function getPusherMessage() |
| { |
| $member_id = 10001;// maybe you can make web notification with Auth. |
| |
| return view('push')->with(compact('member_id')); |
| } |
| } |
| |
程式第 14 ~ 19 行為根據 get 參數生成一個假的使用者,這裏若是未來要開發當然是可以傳入 Laravel 的 Auth User
第 20 行為觸發此事件。
app\Events\SendMessage.php
| |
| |
| namespace App\Events; |
| |
| use App\User; |
| use Illuminate\Queue\SerializesModels; |
| use Illuminate\Contracts\Broadcasting\ShouldBroadcast; |
| |
| class SendMessage extends Event implements ShouldBroadcast |
| { |
| use SerializesModels; |
| |
| private $user; |
| |
| private $message; |
| |
| /** |
| * Create a new event instance. |
| * |
| * @return void |
| */ |
| public function __construct(Array $user, $message = '') |
| { |
| $this->user = $user; |
| $this->message = $message; |
| } |
| |
| /** |
| * Payload |
| * |
| * @return array |
| */ |
| public function broadcastWith() |
| { |
| return [ |
| 'id' => $this->user['id'], |
| 'username' => $this->user['username'], |
| 'message' => $this->message, |
| ]; |
| } |
| |
| /** |
| * Get the channels the event should be broadcast on. |
| * |
| * @return array |
| */ |
| public function broadcastOn() |
| { |
| return ['laravel-tutorial-event-channel-'.$this->user['id']]; |
| } |
| } |
函式 broadcastWith() 將想帶入得值寫入,函式 broadcastOn() 將設置此事件的廣播頻道。
views\push.blade.php
| |
| <html> |
| <head> |
| <title>Laravel</title> |
| <script src="/bower_components/jquery/dist/jquery.js"></script> |
| <script src="https://js.pusher.com/3.1/pusher.min.js"></script> |
| <style> |
| #message { |
| height:300px; |
| width:30% |
| background-color: #cccccc; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <div class="row"> |
| <div class="col-md-6 col-md-offset-3"> |
| <h1>Laravel Event Broadcasting Demo</h1> |
|
|
| |
| <div id="message"> |
| </div> |
|
|
| </div> |
| </div> |
| </div> |
| </body> |
| <script> |
| // Enable pusher logging - don't include this in production |
| Pusher.logToConsole = true; |
| |
| var pusher = new Pusher('{{env('PUSHER_KEY','')}}', { |
| cluster: 'ap1', |
| encrypted: true |
| }); |
| |
| var channel = pusher.subscribe('laravel-tutorial-event-channel-{{$member_id}}'); |
| |
| channel.bind('App\\Events\\SendMessage', function(data) { |
| $('#message').append(''+data.username + ': '+ data.message + ' |
');
| }); |
| |
| </script> |
| </html> |
|
|
程式 第 6 行為將 pusher 的函式庫以cdn的方式傳入,程式碼 33 行為設置監聽的頻道與叢集(cluster),第 38 行設置監聽頻道,第 40 行為監聽的 Event 名稱(此例為針對不同使用者應要會取得不同內容)
作者的話:redis 的方法將會在 下一篇與大家說明。
reference : http://codingweb.tw/2016/06/28/laravel-5-event-broadcasting(事件廣播)進階篇-pusher/