J'ai déjà dit que je compilerais un tutoriel sur la diffusion d'événements. Aujourd'hui, j'ai enfin le temps d'écrire cet article. Ce tutoriel est basé sur Laravel+Pusher+Vue, avec la diffusion d'événements comme technologie de base, vous permettant de créer rapidement. une application de salle de discussion en temps réel. Sans plus tarder, jetons un coup d'œil au contenu spécifique.
Initialisation de l'application
Configuration de l'installation
Tout d'abord, installez une nouvelle application de salle de discussion via Composer :
composer create-project laravel/laravel chatroom --prefer-dist
Parce que utilisez la diffusion d'événements, vous devez décommenter le fournisseur de services de diffusion dans config/app.php :
Modifiez l'élément de configuration BROADCAST_DRIVER dans .env en pusher :
BROADCAST_DRIVER=pusher
Bien que Laravel prenne en charge Pusher dès le départ, nous devons toujours installer le SDK PHP correspondant :
composer require pusher/pusher-php-server
Définir les informations d'identification de Pusher
Visitez le site officiel de Pusher, inscrivez-vous et connectez-vous au backend utilisateur, et créez une nouvelle application Channels :
Une fois la création terminée, vous pouvez obtenir les clés d'application sur la page de saut. Informations :
Remplissez simplement les champs correspondants dans les éléments de configuration correspondants dans .env dans le répertoire racine de l'application de salle de discussion.
Initialisation des ressources front-end
Nous utilisons Laravel Mix pour compiler du CSS et du JavaScript front-end :
npm install
De plus, Laravel fournit également la bibliothèque JavaScript Laravel Echo pour vous abonner et écouter les événements :
npm install --save laravel-echo pusher-js
Une fois l'installation terminée, vous devez également dire à Laravel Echo d'utiliser Pusher. Laravel nous a fourni cette implémentation dans resources/assets/js/bootstrap. js, mais il est commenté par défaut. Il suffit d'annuler ce commentaire :
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 });
Code d'échafaudage d'authentification de l'utilisateur
Nous avons défini que seuls les utilisateurs connectés peuvent accéder à la salle de discussion pour chat. Afin de simplifier le processus, nous utilisons la fonction d'authentification utilisateur par défaut de Laravel :
php artisan make:auth
La commande ci-dessus générera le routage, la vue, le contrôleur et d'autres codes nécessaires au système d'authentification utilisateur. Avant que la fonction ne prenne effet, vous devez exécuter la commande de migration de base de données pour générer la table de données correspondante, modifier les éléments de configuration liés à la base de données dans .env pour vous assurer que la base de données peut être connectée correctement, puis exécuter la commande suivante :
php artisan migrate
À ce stade, l'application est initialisée. Le travail de préparation est terminé, commençons à écrire le code métier.
Implémentation du code métier
Modèle de message
Créez d'abord une classe de modèle et son fichier de migration de base de données correspondant pour le message envoyé :
php artisan make:model Message -m
Ajoutez la ligne de code suivante à la classe de modèle d'application/message nouvellement générée pour faciliter l'affectation par lots :
/** * Fields that are mass assignable * * @var array */ protected $fillable = ['message'];
Écrivez ensuite le fichier de migration correspondant aux messages nouvellement générés dans le répertoire bases de données/migrations La méthode up :
Schema::create('messages', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->text('message'); $table->timestamps(); });
Exécutez enfin la commande de migration pour générer les messages de la table de données :
php artisan migrate
Association entre utilisateurs et messages
Évidemment, la relation entre utilisateurs et messages Il existe une relation un-à-plusieurs. Ajoutez une nouvelle méthode d'association dans la classe de modèle Utilisateur :
/** * A user can have many messages * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function messages() { return $this->hasMany(Message::class); }
Ensuite, définissez l'association correspondante dans la classe de modèle Message :
<🎜. >/** * A message belong to a user * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() { return $this->belongsTo(User::class); }
php artisan make:controller 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('auth'); // 登录用户才能访问 } /** * Show chats * * @return \Illuminate\Http\Response */ public function index() { return view('chat'); } /** * Fetch all messages * * @return Message */ public function fetchMessages() { return Message::with('user')->get(); } /** * Persist message to database * * @param Request $request * @return Response */ public function sendMessage(Request $request) { $user = Auth::user(); $message = $user->messages()->create([ 'message' => $request->input('message') ]); return ['status' => 'Message Sent!']; } }
Route::get('/', 'ChatsController@index'); Route::get('messages', 'ChatsController@fetchMessages'); Route::post('messages', 'ChatsController@sendMessage');
protected $redirectTo = '/';
@extends('layouts.app') @section('content') <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
<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>
<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: ['messages'] }; </script>
<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: ['user'], data() { return { newMessage: '' } }, methods: { sendMessage() { this.$emit('messagesent', { user: this.user, message: this.newMessage }); this.newMessage = '' } } } </script>
require('./bootstrap'); window.Vue = require('vue'); Vue.component('chat-messages', require('./components/ChatMessages.vue')); Vue.component('chat-form', require('./components/ChatForm.vue')); const app = new Vue({ el: '#app', data: { messages: [] }, created() { this.fetchMessages(); }, methods: { fetchMessages() { axios.get('/messages').then(response => { this.messages = response.data; }); }, addMessage(message) { this.messages.push(message); axios.post('/messages', message).then(response => { console.log(response.data); }); } } });
php artisan make:event 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('chat'); } }
由于只有登录用户才能访问我们的应用,所以我们定义了一个私有的频道 chat,只有登录用户才能连接上它。
接下来,我们需要修改 ChatsController 的 sendMessage() 来广播 MessageSent 事件:
public function sendMessage(Request $request) { $user = Auth::user(); $message = $user->messages()->create([ 'message' => $request->input('message') ]); broadcast(new MessageSent($user, $message))->toOthers(); return ['status' => 'Message Sent!']; }
然后在 routes/channels.php 中授权当前登录用户可以监听该私有频道:
Broadcast::channel('chat', function ($user) { return Auth::check(); });
现在,当一条消息发送后,MessageSent 事件就会被广播到 Pusher,使用 toOthers() 是为了将消息发送者从广播接收者中排除。
监听消息发送事件
MessageSent 事件在服务端被广播后,需要在客户端监听这个事件以便将最新发送消息更新到聊天室消息流中,我们可以通过在 resources/assets/js/app.js 中定义的 created() 方法中添加如下代码片段来实现这一功能:
created() { this.fetchMessages(); Echo.private('chat') .listen('MessageSent', (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用户授权和权限检查功能的实现
相关课程推荐:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!