ホームページ  >  記事  >  PHPフレームワーク  >  リアルタイムチャットルーム:Laravel+Pusher+Vueをベースとしたイベントブロードキャストにより実装

リアルタイムチャットルーム:Laravel+Pusher+Vueをベースとしたイベントブロードキャストにより実装

不言
不言オリジナル
2018-07-31 15:48:545375ブラウズ

前にイベント ブロードキャストに関するチュートリアルを作成すると言いましたが、今日ようやくこの記事を書く時間ができました。このチュートリアルは、イベント ブロードキャストをコア テクノロジとして使用しており、リアルタイム チャット ルーム アプリケーション。早速、具体的なコンテンツを見てみましょう。

アプリケーションの初期化

インストールと構成

まず、Composer を通じて新しいチャット ルーム アプリケーションをインストールします:

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

イベント ブロードキャストが使用されるため、config/app.php でブロードキャスト サービス プロバイダーのコメントを解除する必要があります:

リアルタイムチャットルーム:Laravel+Pusher+Vueをベースとしたイベントブロードキャストにより実装

.env の BROADCAST_DRIVER 設定項目をプッシャーに変更します:

BROADCAST_DRIVER=pusher

Laravel はすぐに使えるプッシャーをサポートしていますが、対応する PHP SDK をインストールする必要があります:

composer require pusher/pusher-php-server

プッシャー認証情報を設定します

Pusher 公式 Web サイトにアクセスし、ユーザー バックエンドに登録してログインし、新しいチャンネル アプリを作成します:

リアルタイムチャットルーム:Laravel+Pusher+Vueをベースとしたイベントブロードキャストにより実装

作成が完了したら、ジャンプ ページでアプリ キーを取得できます:

リアルタイムチャットルーム:Laravel+Pusher+Vueをベースとしたイベントブロードキャストにより実装

対応するフィールドに入力します。チャット ルーム アプリケーションのルート ディレクトリにある .env 内の対応する設定項目で十分です。

フロントエンドリソースの初期化

フロントエンドCSSとJavaScriptをコンパイルするためにLaravel Mixを使用します:

npm install

さらに、LaravelはサブスクライブしてイベントをリッスンするためのJavaScriptライブラリLaravel Echoも提供します:

npm install --save laravel-echo pusher-js

インストール後は完了したら、Laravel Echo に Pusher を使用するように指示する必要もあります。Laravel は、resources/assets/js/bootstrap.js でこの実装を提供しましたが、デフォルトではコメントアウトされています:

import Echo from 'laravel-echo'
window.Pusher = require('pusher-js');
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    encrypted: true
});

のセクションのコメントを解除するだけです。ユーザー認証スキャフォールディングコード

プロセスを簡素化するために、ログインしたユーザーのみがチャットルームに入ることができるように設定します:

php artisan make:auth

上記のコマンドはルーティングを生成します。ユーザー認証システムに必要なビュー、コントローラー、その他のコード。関数が有効になる前に、データベース移行コマンドを実行して対応するデータ テーブルを生成し、.env 内のデータベース関連の構成項目を編集してデータベースが正しく接続できることを確認してから、次のコマンドを実行する必要があります:

php artisan migrate

この時点で、以下のようにアプリケーションの初期化の準備が完了しました。 ビジネスコードの記述を開始します。

ビジネス コードの実装

メッセージ モデル

まず、送信メッセージのモデル クラスとそれに対応するデータベース移行ファイルを作成します。

php artisan make:model Message -m

次のコード行を、新しく生成されたアプリ/メッセージ モデル クラスに便利なバッチに追加します。割り当て:

/**
 * Fields that are mass assignable
 *
 * @var array
 */
protected $fillable = ['message'];

次に、データベース/移行ディレクトリに新しく生成されたメッセージを書き込みます。 移行ファイルに対応する up メソッド:

Schema::create('messages', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('user_id')->unsigned();
    $table->text('message');
    $table->timestamps();
});

最後に、移行コマンドを実行して、データ テーブル メッセージを生成します:

php artisan migrate

ユーザーとの関係。メッセージ

は非常に明らかです。ユーザーとメッセージの間には 1 対多の関係があります。User モデル クラスに新しい関連付けメソッドを追加します:

/**
 * A user can have many messages
 *
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function messages()
{
    return $this->hasMany(Message::class);
}

次に、Message モデル クラスで対応する関連付け関係を定義します:

/**
 * A message belong to a user
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 */
public function user()
{
    return $this->belongsTo(User::class);
}

コントローラー コード

特定のビジネス ロジックを実装するコントローラー ChatsController を作成します。

php artisan make:controller ChatsController

新しく生成されたコントローラー クラス app/Http/Controllers/ChatsController を記述します。 コードは次のとおりです。

<?php
namespace App\Http\Controllers;
use Auth;
use App\Message;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class ChatsController extends Controller
{
    public function __construct()
    {
        $this->middleware(&#39;auth&#39;);  // 登录用户才能访问
    }
    /**
     * Show chats
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view(&#39;chat&#39;);
    }
    /**
     * Fetch all messages
     *
     * @return Message
     */
    public function fetchMessages()
    {
        return Message::with(&#39;user&#39;)->get();
    }
    /**
     * Persist message to database
     *
     * @param  Request $request
     * @return Response
     */
    public function sendMessage(Request $request)
    {
        $user = Auth::user();
        $message = $user->messages()->create([
            &#39;message&#39; => $request->input(&#39;message&#39;)
        ]);
        return [&#39;status&#39; => &#39;Message Sent!&#39;];
    }
}

コントローラーは 3 つのビジネス メソッドを提供します。インデックスは次のとおりです。チャット ルーム ビューの表示に使用され、fetchMessages ユーザーはすべてのメッセージを取得し、sendMessage はメッセージの送信に使用されます。

アプリケーションルートを登録します

これに応じて、routes/web.php に 3 つのルートを登録します。

Route::get(&#39;/&#39;, &#39;ChatsController@index&#39;);
Route::get(&#39;messages&#39;, &#39;ChatsController@fetchMessages&#39;);
Route::post(&#39;messages&#39;, &#39;ChatsController@sendMessage&#39;);

対応して、登録されたルートから /home ルートを削除します。 app/Http/Controllers/Auth/LoginController .php を追加する必要があります。

protected $redirectTo = &#39;/&#39;;

チャット ルーム ビュー

チャット ルーム ビュー コードについては、Bootsnipp チャット ルーム コード スニペットに基づいてわずかな調整を加えました。まず、resources/views/chat.blade.php を作成します:

@extends(&#39;layouts.app&#39;)
@section(&#39;content&#39;)
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    <div class="panel-heading">聊天室</div>
                    <div class="panel-body">
                        <chat-messages :messages="messages"></chat-messages>
                    </div>
                    <div class="panel-footer">
                        <chat-form
                                v-on:messagesent="addMessage"
                                :user="{{ Auth::user() }}"
                        ></chat-form>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

このビューは、チャット ルームのメイン ページを表示するために使用されます。ビューでいくつかの Vue コンポーネントを使用していることに注意してください。チャット メッセージ コンポーネントはすべてのチャット メッセージを表示するために使用され、チャット フォーム コンポーネントはメッセージを送信するために使用されます。これらのコンポーネントのコードは後で説明します。

Vue コンポーネントを記述する前に、チャット ビューのスタイル コードを resource/views/layouts/app.blade.php テンプレートに追加します ( タグに追加する前に):

<style>
  .chat {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .chat li {
    margin-bottom: 10px;
    padding-bottom: 5px;
    border-bottom: 1px dotted #B3A9A9;
  }
  .chat li .chat-body p {
    margin: 0;
    color: #777777;
  }
  .panel-body {
    overflow-y: scroll;
    height: 350px;
  }
  ::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
    background-color: #F5F5F5;
  }
  ::-webkit-scrollbar {
    width: 12px;
    background-color: #F5F5F5;
  }
  ::-webkit-scrollbar-thumb {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
    background-color: #555;
  }
</style>

Next in Resources/ Assets/js/components に ChatMessages.vue コンポーネントを作成します:

<template>
    <ul class="chat">
        <li class="left clearfix" v-for="message in messages">
            <div class="chat-body clearfix">
                <div class="header">
                    <strong class="primary-font">
                        {{ message.user.name }}
                    </strong>
                </div>
                <p>
                    {{ message.message }}
                </p>
            </div>
        </li>
    </ul>
</template>
<script>
    export default {
        props: [&#39;messages&#39;]
    };
</script>

次に、同じディレクトリに ChatForm.vue コンポーネントを作成します:

<template>
    <div class="input-group">
        <input id="btn-input" type="text" name="message" class="form-control input-sm" placeholder="在这里输入要发送的消息..." v-model="newMessage" @keyup.enter="sendMessage">
        <span class="input-group-btn">
            <button class="btn btn-primary btn-sm" id="btn-chat" @click="sendMessage">
                发送
            </button>
        </span>
    </div>
</template>
<script>
    export default {
        props: [&#39;user&#39;],
        data() {
            return {
                newMessage: &#39;&#39;
            }
        },
        methods: {
            sendMessage() {
                this.$emit(&#39;messagesent&#39;, {
                    user: this.user,
                    message: this.newMessage
                });
                this.newMessage = &#39;&#39;
            }
        }    
    }
</script>

最後に、これら 2 つのコンポーネントを resource/assets/js/app に登録する必要があります。 js Vue ルート インスタンス内:

require(&#39;./bootstrap&#39;);
window.Vue = require(&#39;vue&#39;);
Vue.component(&#39;chat-messages&#39;, require(&#39;./components/ChatMessages.vue&#39;));
Vue.component(&#39;chat-form&#39;, require(&#39;./components/ChatForm.vue&#39;));
const app = new Vue({
    el: &#39;#app&#39;,
    data: {
        messages: []
    },
    created() {
        this.fetchMessages();
    },
    methods: {
        fetchMessages() {
            axios.get(&#39;/messages&#39;).then(response => {
                this.messages = response.data;
            });
        },
        addMessage(message) {
            this.messages.push(message);
            axios.post(&#39;/messages&#39;, message).then(response => {
                console.log(response.data);
            });
        }
    }
});

ブロードキャスト メッセージ送信イベント

チャット ルームでリアルタイムの対話を行うには、特定のイベントをブロードキャストする必要があります。この場合、ユーザーが送信するときに MessageSent イベントをトリガーします。メッセージ:

php artisan make:event MessageSent

書かれた app/Events/MessageSent イベント クラス コードは次のとおりです:

<?php
namespace App\Events;
use App\Message;
use App\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class MessageSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    /**
     * User that sent the message
     *
     * @var User
     */
    public $user;
    /**
     * Message details
     *
     * @var Message
     */
    public $message;
    /**
     * Create a new event instance.
     * @param User $user
     * @param Message $message
     * @return void
     */
    public function __construct(User $user, Message $message)
    {
        $this->user = $user;
        $this->message = $message;
    }
    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel(&#39;chat&#39;);
    }
}

由于只有登录用户才能访问我们的应用,所以我们定义了一个私有的频道 chat,只有登录用户才能连接上它。

接下来,我们需要修改 ChatsController 的 sendMessage() 来广播 MessageSent 事件:

public function sendMessage(Request $request)
{
    $user = Auth::user();
    $message = $user->messages()->create([
        &#39;message&#39; => $request->input(&#39;message&#39;)
    ]);
    broadcast(new MessageSent($user, $message))->toOthers();
    return [&#39;status&#39; => &#39;Message Sent!&#39;];
}

然后在 routes/channels.php 中授权当前登录用户可以监听该私有频道:

Broadcast::channel(&#39;chat&#39;, function ($user) {
    return Auth::check();
});

现在,当一条消息发送后,MessageSent 事件就会被广播到 Pusher,使用 toOthers() 是为了将消息发送者从广播接收者中排除。

监听消息发送事件

MessageSent 事件在服务端被广播后,需要在客户端监听这个事件以便将最新发送消息更新到聊天室消息流中,我们可以通过在 resources/assets/js/app.js 中定义的 created() 方法中添加如下代码片段来实现这一功能:

created() {
    this.fetchMessages();
    Echo.private(&#39;chat&#39;)
        .listen(&#39;MessageSent&#39;, (e) => {
            this.messages.push({
                message: e.message.message,
                user: e.user
            });
        });
},

我们通过 Laravel Echo 连接到 chat 频道监听 MessageSent 广播事件,如果有新消息则将其推送到当前聊天室消息流中显示。

在正式测试聊天室应用之前,还需要运行以下命令通过 Laravel Mix 来编译前面编写的 JavaScript 代码:

npm run dev

使用示例

完成上述所有业务代码编写工作后,接下来就是见证工作成果的时候了,在项目根目录下运行如下命令启动应用:

php artisan serve

然后在浏览器通过 http://127.0.0.1:8000/ 访问应用,由于系统需要登录后才能访问,所以首先会跳转到登录页面,我们需要先注册一个新用户,注册成功后页面即跳转到聊天室页面,我们发送一条测试消息。

为了测试多个用户聊天的效果,打开另一个浏览器或者在当前浏览器新开一个隐身窗口,还是重复上面的访问注册步骤(注册名不同),注册成功后跳转到聊天室页面,看到的效果和上面一样,我们再发条消息试试。

可以看到两个窗口消息是同步的,所以已经达到我们预期的实时聊天效果,实现了通过事件广播构建实时聊天室的功能。

以上就是本篇文章的全部内容了,更多laravel内容请关注laravel框架入门教程。

相关文章推荐:

laravel框架中TokenMismatchException的异常处理内容

Laravel 5.1框架中的ACL用户授权和权限检查功能的实现

相关课程推荐:

2017年最新的五个Laravel视频教程推荐

以上がリアルタイムチャットルーム:Laravel+Pusher+Vueをベースとしたイベントブロードキャストにより実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。