Laravel - Digging Deeper - Broadcasting (官方文件原子化翻譯筆記)

# 前言

學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。



# Introduction

# Configuration

Laravel 中, 有關 broadcast 的設定都在哪一個檔案中?

config/broadcasting.php

Laravel 中, 要啟動 BroadcastServiceProvider, 預設要到 哪個檔案哪個 property 去 uncomment 這個 provider?

config/app.php

Laravel Broadcast 中, Laravel Echo 會存取 session 中的什麼東西?

CSRF token

Laravel Broadcast 中, Laravel Echo 預設會存取 session 當中的 CSRF token, 所以要在 HTML 的哪一個 tag 中載入 csrf-token?

meta tag

Laravel 中, 當使用 broadcast 時, 以下的 blade view example 的意思是?
  • Example:
    <?php
    <meta name="csrf-token" content="{{ csrf_token() }}">
  • Answer:
    Laravel Broadcast 中, 預設 Laravel Echo 會存取 session 當中的 CSRF token, 並以此跟 server 驗證, 所以當不是使用 SPA 時, 需在 meta tag 內置入 csrf_token

# Driver Prerequisites

# Pusher Channels

Laravel Broadcast 中, 如果是使用 Pusher Channels 的方式, 需要另外安裝 sdk 嗎?

需要

composer require pusher/pusher-php-server "~4.0"
解釋以下的 Laravel Echo javascript code
  • Example:
    import Echo from "laravel-echo";

    window.Pusher = require('pusher-js');

    window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key'
    });
  • Answer:
    // 載入 Echo
    import Echo from "laravel-echo";

    // 載入 pusher-js
    window.Pusher = require('pusher-js');

    // 定義 echo
    window.Echo = new Echo({
    // channel name
    broadcaster: 'pusher',
    // channel key
    key: 'your-pusher-channels-key'
    });
Laravel Broadcast 中, 若使用 Pusher Channel, 那以下的 .env example 該填入?
  • Example:
    <?php
    BROADCAST_DRIVER=這邊要填什麼?
  • Answer:
    <?php
    BROADCAST_DRIVER=pusher

# Redis

Laravel Broadcast 中, 當我使用 Redis 時, 可使用哪兩種方式安裝 Redis?
  • PECL
  • Composer
Laravel Broadcast 中, 當我使用 Composer 安裝 Redis 時, 可以使用哪個 CLI?
composer require predis/predis
Laravel Broadcast 中, 如果我使用 Redis 來 Broadcast, 那以下的 .env example 當中該填入什麼?
  • Example:
    <?php
    BROADCAST_DRIVER=這裡要填什麼
  • Answer:
    <?php
    BROADCAST_DRIVER=redis
Laravel Broadcast 中, 如果我使用 Redis 來 Broadcast, 我必須要將 Redis 跟哪一種類型的 server 做配對?

WebSocket

# Socket.IO

Laravel Broadcast 中, 如果我使用 Redis 配對 socket.io server, 前端需要安裝什麼?

Socket.IO Javascript client library

npm install --save socket.io-client
Laravel Broadcast 中, 解釋以下 JavaScript example
  • Example:
    import Echo from "laravel-echo"

    window.io = require('socket.io-client');

    window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001'
    });
  • Answer:
    // import Larave Echo
    import Echo from "laravel-echo"

    // require socket.io-client
    window.io = require('socket.io-client');

    window.Echo = new Echo({
    // broadcast type
    broadcaster: 'socket.io',
    // host
    host: window.location.hostname + ':6001'
    });
Laravel Broadcast 中, 如果我使用 Redis, 那我安裝什麼 server 在後端?

socket.IO server



# Concept Overview

# Using An Example Application

# The ShouldBroadcast Interface

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Events;

    class ShippingStatusUpdated implements ShouldBroadcast
    {
    public $update;
    }
  • Answer:
    在 event class implement ShouldBroadcast
Laravel Broadcast 中, 以下 broadcastOn method 的用途是?
  • Example:

    <?php
    /**
    * Get the channels the event should broadcast on.
    *
    * @return \Illuminate\Broadcasting\PrivateChannel
    */
    public function broadcastOn()
    {
    return new PrivateChannel('order.'.$this->update->order_id);
    }
  • Answer:
    return 這個 event 需要 broadcast 的 channel


# Authorizing Channels

解釋以下的 Laravel example
  • Example:
    <?php
    Broadcast::channel('order.{orderId}', function ($user, $orderId) {
    return $user->id === Order::findOrNew($orderId)->user_id;
    });
  • Answer:
    <?php
    // Authorize channel, 驗證該 order 的建立者是否為該 user
    Broadcast::channel('order.{orderId}', function ($user, $orderId) {
    return $user->id === Order::findOrNew($orderId)->user_id;
    });
Laravel Broadcast 中, 當我 authorize channel 時, 以下的 closure 的回傳值是什麼?
  • Example:
    <?php
    Broadcast::channel('order.{orderId}', function ($user, $orderId) {
    // 這邊要回傳?
    });
  • Answer:
    boolean

# Listening For Event Broadcasts

Laravel Broadcast 中, 解釋以下 JavaScript example
  • Example:

    Echo.private(`order.${orderId}`)
    .listen('ShippingStatusUpdated', (e) => {
    console.log(e.update);
    });
  • Answer:

    // 監聽 order.${orderId} channel 中的 'ShippingStatusUpdated' 事件, 並 console.log 名為 update 的 public property
    Echo.private(`order.${orderId}`)
    .listen('ShippingStatusUpdated', (e) => {
    console.log(e.update);
    });


# Defining Broadcast Events

Laravel Broadcast 中, 一個 event 可以被廣播到多個 channel 嗎?

可以

Laravel Broadcast 中, 有哪三種 channel interface?
  • Channel
  • PrivateChannel
  • PresenceChannel
Laravel Broadcast 中, public channel 是屬於哪一種 channel interface?

Channel

Laravel 中, PrivateChannels 以及 PresenceChannels 屬於 private channel 還是 public channel?

private

Laravel 中, PrivateChannels 以及 PresenceChannels 需要通過 channel authorization 嗎?

需要


# Broadcast Name

以下的 Laravel example command 的意思是?
  • Example:
    <?php

    namespace App\Events;

    use App\User;
    use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
    use Illuminate\Queue\SerializesModels;

    class ServerCreated implements ShouldBroadcast
    {
    use SerializesModels;

    public $user;

    public function __construct(User $user)
    {
    $this->user = $user;
    }

    public function broadcastAs()
    {
    return 'server.created';
    }
    }
  • Answer:
    自定義 event name
Laravel 中, 當我使用 broadcastAs() method 時, 那在註冊 listener 時, 要注意什麼?

要在 event name 的前面加一個 .

Laravel 中, 當我使用 broadcastAs() method 時, 那在註冊 listener 時, 要在 event name 前加個 . 如下, 為何??
  • Example:
    <?php
    .listen('.server.created', function (e) {
    ....
    });
  • Answer:
    因為加了 . 之後, Echo 就不會自己在前面加上 namespace

# Broadcast Data

Laravel Broadcast 中, 當我廣播一個 event 時, 預設會將什麼資料帶過去?

該 event 中的所有 public property

Laravel Broadcast 中, 當我廣播一個 event 時, 如果我有一個 public property 是 User model 的 instance, 那到了前端會變成什麼資料?

一個 object

Laravel Broadcast 中, 當我廣播一個 event 時, 如果我要控管傳送過去的資料, 那我可以使用哪一個 method?

broadcastWith() method

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Events;

    class ServerCreated implements ShouldBroadcast
    {
    use SerializesModels;

    public $user;

    public function __construct(User $user)
    {
    $this->user = $user;
    }

    public function broadcastWith()
    {
    return ['id' => $this->user->id];
    }
    }
  • Answer:
    定義 broadcast 時帶過去的資料 key / value

# Broadcast Queue

Laravel 中, Broadcast queue 預設是使用哪一組 queue?

預設於 queue.php 檔案中的 queue

Laravel 中, 如果我想要自定義 broadcast 使用到的 queue, 可以在該 event 中新增 哪一個 property?

$broadcastQueue property

Laravel 中, 如果我想要使用 sync queue, 而不使用預設的, 那請回答以下 example 中的問題
  • Example:
    <?php

    use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

    class ShippingStatusUpdated implements 這裡該填入?
    {
    //
    }
  • Answer:
    <?php

    use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

    class ShippingStatusUpdated implements ShouldBroadcastNow
    {
    //
    }

# Broadcast Conditions

Laravel 中, 如果我想要當某些條件成立時, 我才 broadcast event, 那我可以使用 哪一個 method ?

broadcastWhen() method

Laravel 中, 如果我想要定義, 當 value property 的值大於 100 時, 我才 broadcast event, 那請回答以下 example 中的問題
  • Example:
    <?php
    public function broadcastWhen()
    {
    // 這裡該 return?
    }
  • Answer:
    <?php
    public function broadcastWhen()
    {
    return $this->value > 100;
    }


# Authorizing Channels

Laravel broadcast 中, private channel 要被監聽之前, 需要經過 Laravel authorize 嗎?

需要哦

Laravel broadcast中, Laravel Echo 會自動地幫我們發 authorization request 嗎?

會哦

# Defining Authorization Routes

Laravel broadcast 中, 哪個 class哪個 method 負責註冊 /broadcasting/auth 來處理 authorization request?
  • Broadcast class
  • routes() method
Laravel broadcast 中, 當我使用 Broadcast::routes 時, 預設會使用哪一個 middleware group?

web middleware

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    Broadcast::routes(['middleare' => 'api']);
  • Answer:
    Laravel Broadcast 預設會使用 web middleware group, 如果要使用 api middleware group 的話, 可在 routes() 中指定

# Customizing The Authorization Endpoint

Laravel Broadcast 中, Laravel Echo 預設是使用哪一個 endpoint 來 authorize channel?

/broadcasting/auth

Laravel Broadcast 中, Laravel Echo 預設使用 /broadcasting/auth endpoint 來 authorize channel, 如果我要自定義為 /custom/endpoint/auth 的話, 在以下的 example 中可以怎麼做?
  • Example:
    <?php
    window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    // 這邊該填入?
    });
  • Answer:
    <?php
    window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    authEndpoint: '/custom/endpoint/auth'
    });


# Defining Authorization Callbacks

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    Broadcast::channel('channelName', Authorization callback);
  • Answer:
    Broadcast channel, arg1 接受 channel name, arg2 接受驗證 callback
Laravel Broadcast 中, Broadcast::channel method 的 authorization callback 需 return 什麼?

boolean

Laravel Broadcast 中, Broadcast::channel method 的 callback 接收哪兩個參數如下 example?
  • Example:
    <?php
    Broadcast::channel('order.{orderId}', function (這裡是?, 這裡又是?) {
    return $user->id === Order::findOrNew($orderId)->user_id;
    });
  • Answer:
    <?php
    Broadcast::channel('order.{orderId}', function ($authenticatedUser, $wildcard) {
    return $user->id === Order::findOrNew($orderId)->user_id;
    });

# Authorization Callback Model Binding

Laravel Broadcast 中, 在以下的 example 如果我想要以 model binding 的方式 bind $order, 我可以怎麼做?
  • Example:
    <?php
    use App\Order;

    Broadcast::channel('order.{order}', function ($user, 要怎麼做呢?) {
    return $user->id === $order->user_id;
    });
  • Answer:
    <?php
    use App\Order;

    Broadcast::channel('order.{order}', function ($user, Order $order) {
    return $user->id === $order->user_id;
    });

# Authorization Callback Authentication

Laravel Broadcast 中, private 以及 presence channel 是透過什麼來 authenticate current user?

Application’s default authentication guard

Laravel Broadcast 中, 如果 user authentication 沒過, 那 authorization callback 會被執行嗎?

不會

Laravel Broadcast 中, 如果我要指定以下 example 中的 guards, 假設為 ‘web’, 以及 ‘admin’, 可以怎麼做?
  • Example:
    <?php
    Broadcast::channel('channel', function () {
    // ...
    }, 可以怎麼做呢?);
  • Answer:
    <?php
    Broadcast::channel('channel', function () {
    // ...
    }, ['guards' => ['web', 'admin']]);

# Defining Channel Classes

Laravel Broadcast 中, 如果我們的應用使用了大量不同的 channel, 那在 routes/channels.php 檔案中可能被滿滿的 closure 所佔據, 所以我們可以使用 CLI 來建立專屬的 channel class, 該怎麼做呢?
php artisan make:channel ChannelName
Laravel Broadcast 中, 如果我們的應用使用了大量不同的 channel, 那在 routes/channels.php 檔案中可能被滿滿的 closure 所佔據, 所以我們可以使用 CLI 來建立專屬的 channel class, 建立好的 channel, 要在哪裡註冊呢?

routes/channels.php

以下的 Laravel example code 的意思是?
  • Example:
    <?php
  • Answer:
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use App\Broadcasting\OrderChannel;

    Broadcast::channel('order.{order}', OrderChannel::class);
  • Answer:
    將存取 channel order.{order} 的驗證 closure 寫成一個 class OrderChannel
Laravel Broadcast 中, 如果我們的應用使用了大量不同的 channel, 那在 routes/channels.php 檔案中可能被滿滿的 closure 所佔據, 所以我們可以使用 CLI 來建立專屬的 channel class, 建立好的 channel, 建立好的 channel class 中, 原本我們寫在 closure 中的 authorization logic 要寫在 channel class 中的哪個 method 呢?

join method

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App\Broadcasting;

    use App\Order;
    use App\User;

    class OrderChannel
    {
    public function __construct()
    {
    //
    }

    public function join(User $user, Order $order)
    {
    return $user->id === $order->user_id;
    }
    }
  • Answer:
    在自定義的 channel class 中, 使用 join method 來定義 authorization logic, 即驗證 authenticated user 是否可存取該 channel 的 logic


# Broadcasting Events

Laravel Broadcast 中, 如果我要廣播一個 event 的話, 可以使用哪兩個 method?
  • event function
  • broadcast function

# Only To Others

Laravel Broadcast 中, 如果我要廣播一個 event, 我可以使用 event function 或是 broadcast function, 兩者的差異是?

broadcast function 可以接 toOthers method

Laravel Broadcast 中, toOthers method 的使用情境是?

當 client 發出一個 request, 這個 request 的 response 已經做了一件事, 如果這時候還收到 broadcast, 那就會同一件事情做了兩次

Laravel Broadcast 中, toOthers method 的用途是?

不會 broadcast 該 event 給 authenticated user

Laravel Broadcast 中, 如果要使用 toOthers method 的話, 必須要 use 哪一個 interface?

Illuminate\Broadcasting\InteractsWithSockets interface


# Configuration

Laravel Broadcast 中, 當使用 toOthers method 時, Laravel 是從哪裡判斷哪一個 connection 不要 broadcast 事件?

X-Socket-ID header

Laravel Broadcast 中, 當我使用 Vue 以及 Axios 時, 會自動附加哪一個 header, 而單純使用 JavaScript 不會附加?

X-Socket-ID header

Laravel Broadcast 中, 當我使用 Vue 以及 Axios 時, 會自動 X-Socket-ID header, 但使用 JavaScript 時並不會自動附加, 這時候可以從哪一個 method 取得 X-Socket-ID?

Echo.socketId



# Receiving Broadcasts

# Installing Laravel Echo

Laravel Broadcast 中, 如果我要使用 npm CLI 來安裝 Laravel Echo 以及 pusher-js package 時, 可以怎麼做?
npm install --save laravel-echo pusher-js
Laravel Broadcast 中, 如果我已經安裝好 Laravel Echo, 可以在哪個檔案中建立一個 Echo instance?

resources/js/bootstrap.js

以下的 Laravel example code 的意思是?
  • Example:
    window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    cluster: 'eu',
    forceTLS: true
    });
  • Answer:
    強制啟動 HTTPS 連線

# Using An Existing Client Instance

Laravel Broadcast 中, 當我使用 Laravel Echo 時, 如果我已經有 Pusher Channels 或 Socket.io client instance, 而我想要 Echo 去使用它們, 那在以下的 example 中, 我可以怎麼做?
  • Example:
    <?php
    const client = require('pusher-js');

    window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    // 這裡可以使用?
    });
  • Answer:
    <?php
    const client = require('pusher-js');

    window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    client: client
    });

# Listening For Events

以下的 Laravel example code 的意思是?
  • Example:
    Echo.channel('orders')
    .listen('OrderShipped', (e) => {
    console.log(e.order.name);
    });
  • Answer:
    監聽 orders channel, OrderShipped event, listener 的邏輯為 console.log(e.order.name)
Laravel Broadcast 中, 當我使用 Laravel Echo 時, 如果我要監聽一個 event, 在下面的 example 中可以怎麼做?
  • Example:
    Echo.channel('orders')
    .這裡使用哪一個method('OrderShipped', (e) => {
    console.log(e.order.name);
    });
  • Answer:
    Echo.channel('orders')
    .listen('OrderShipped', (e) => {
    console.log(e.order.name);
    });
Laravel Broadcast 中, 當我使用 Laravel Echo 時, 如果我要監聽一個 private channel, 在下面的 example 中可以怎麼做?
  • Example:
    Echo.這裡使用哪一個mehtod('orders')
    .listen('event1')
    .listen('event2')
    .listen('event3');
  • Answer:
    Echo.private('orders')
    .listen('event1')
    .listen('event2')
    .listen('event3');
Laravel Broadcast 中, 當我使用 Laravel Echo 時, 如果我要監聽多個 event, 在下面的 example 中可以怎麼做?
  • Example:
    Echo.private('orders')
  • Answer:
    Echo.private('orders')
    .listen('event1')
    .listen('event2')
    .listen('event3');

# Leaving A Channel

Laravel Broadcast 中, 如果我要離開一個 public channel order, 可以使用 Echo 的哪個 method?
Echo.leaveChannel('order');
以下的 Laravel-Echo example code 的意思是?
  • Example:
    Echo.leave('channel');
  • Answer:
    離開所有的 channel, 不論是 public, private, 或 presence

# Namespaces

Laravel Broadcast 中, Laravel Echo 會自動的附加 namespace, 這個 namespace 是?

App\Events

Laravel Broadcast 中, Laravel Echo 會自動的附加 namespace, 如果我想要自定義這個 namespace, 假設為, App\SpecialEvents 在以下的 example 中, 可以怎麼做?
  • Example:

    window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    });
  • Answer:

    window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    namespace: 'App.SpecialEvents'
    });
以下的 Laravel example code 的意思是?
  • Example:
    Echo.channel('orders')
    .listen('.App\\SpecialEvents\\Class', (e) => {
    //
    });
  • Answer:
    Laravel Echo 會自動的附加 namespace, 如果我想要自定義 listen event class 路徑, 可在前面加個 .


# Presence Channels

# Authorizing Presence Channels

Laravel Broadcast 中, Presence channel 跟 Private channel 的差別在於?

Presence channel 可以暴露自己的以及獲得同個 channel 內其他 user 的資訊

Laravel Broadcast 中, 當我使用 Presence channel 時, authorization rule 驗證通過後, 需回傳?

該 user 的 data

Laravel Broadcast 中, 當我使用 Presence channel 時, authorization rule 驗證如果沒通過, 需回傳?

false 或 null

Laravel Broadcast 中, 以下的 example 中的 channel 是 public, private, 或 presence?
  • Example:
    <?php
    Broadcast::channel('chat.{roomId}', function ($user, $roomId) {
    if ($user->canJoinRoom($roomId)) {
    return ['id' => $user->id, 'name' => $user->name];
    }
    });
  • Answer:

Presence channel


# Joining Presence Channels

以下的 Javascript example code 的意思是?
  • Example:
    Echo.join(`chat.${roomId}`)
    .here((users) => {
    //
    });
  • Answer:
    加入一個 presence channel
Laravel Broadcast 中, 以下的 here method 是在什麼時候執行 closure?
  • Example:
    Echo.join(`chat.${roomId}`)
    .here((users) => {
    //
    });
  • Answer:
    當該使用者成功加入頻道時
Laravel Broadcast 中, 以下的 example 中的 joining 內的 closure 會在什麼時機點執行?
  • Example:
    Echo.join(`chat.${roomId}`)
    .joining((user) => {
    console.log(user.name);
    });
  • Answer:
    當有新的 user 加入這個 channel 時
Laravel Broadcast 中, 以下的 example 中的 leaving 內的 closure 會在什麼時機點執行?
  • Example:
    Echo.join(`chat.${roomId}`)
    .leaving((user) => {
    console.log(user.name);
    });
  • Answer:
    當有 user 離開這個 channel 時

# Broadcasting To Presence Channels

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    public function broadcastOn()
    {
    return new PresenceChannel('room.'.$this->message->room_id);
    }
  • Answer:
    在指定的 event 中, 使用 broadcastOn method 來定義該 event 會被 broadcast 到哪個 channel, 使用 PresenceChannel method 來 broadcast 到 presence channel
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    Echo.join(`chat.${roomId}`)
    .here(...)
    .joining(...)
    .leaving(...)
    .listen('NewMessage', (e) => {
    //
    });
  • Answer:
    監聽該 channel 中的 NewMessage presence event


# Client Events

Laravel Broadcast 中, client event 可以用在什麼情境上?

當使用者在輸入文字的時候, 另一邊的使用者可以看到正在輸入中

Laravel Broadcast 中, client event 的特性是?

client 端可以監聽 client 端的 event, 不需透過 server 端

以下的 Laravel example code 的意思是?
  • Example:
    Echo.private('chat')
    .whisper('typing', {
    name: this.user.name
    });
  • Answer:
    使用 Laravel Echo 在 chat private channel 中送出一個 typing client event
以下的 Laravel example code 的意思是?
  • Example:
    Echo.private('chat')
    .listenForWhisper('typing', (e) => {
    console.log(e.name);
    });
  • Answer:
    使用 Laravel Echo, 監聽 typing client event, 並執行 closure 內的邏輯


# Notifications

此章節同 Notification Documentation

Laravel - The Basics - Logging (官方文件原子化翻譯筆記) Laravel - The Basics - Error Handling (官方文件原子化翻譯筆記)

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×