本篇介紹如何在 Laravel 框架中,利用Websocket製作一個聊天室。
思考一下流程
登入→列表→加入聊天室→聊天室→傳送接收訊息(socket)
再來規劃一下大致需要Tables
users(會員)
rooms(聊天室)
user_room(會員跟聊天室的關聯)
messages(聊天訊息)
這裡範例是利用主機當socket
不想設定主機參數可以使用pusher
# 新增Project laravel new {project}
修改env
# .env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=chat_room
PUSHER_APP_KEY=chatchatchat
PUSHER_APP_SECRET=chatchatchatchatchatchat
修改bootstarp.js
# /resources/js/bootstarp.js
import Echo from 'laravel-echo'
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
encrypted: false,
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
wsHost: window.location.hostname,
wsPort: 6001,
forceTLS: false,
disableStats: true
});
安裝套件
# 會員套件&啟用
npm install
composer require laravel/jetstream
php artisan jetstream:install livewire
npm run dev
# socket套件
composer install
composer require pusher/pusher-php-server ^4.1
npm install --save laravel-echo pusher-js
composer require beyondcode/laravel-websockets
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan migrate
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
資料庫規劃
users
rooms
user_room
messages
再來規劃broadcast的channel
至少在聊天室的時候要能及時推播訊息(根據room_id)
(以下為部分代碼)
app\Http\Controllers\MessageController
namespace App\Http\Controllers;
use App\Models\Room;
use App\Models\RoomJoin;
use App\Models\Message;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Events\RoomMessageChannelEvent;
use Carbon\Carbon;
class MessageController extends Controller
{
/**
* @var Room
*/
public $model;
/**
* @var RoomJoin
*/
public $join;
/**
* @var Message
*/
public $message;
/**
* RoomController constructor.
*
* @param Room $room
* @param RoomJoin $join
* @param Message $message
*/
public function __construct(Room $room, RoomJoin $join, Message $message)
{
$this->model = $room;
$this->join = $join;
$this->message = $message;
}
/**
* @param \Illuminate\Http\Request $request
* @param $id
*
* @Author: Roy
* @DateTime: 2021/10/23 下午 12:15
*/
public function store(Request $request, $id)
{
if ($this->checkRoomAndUser($id) === false) {
return response()->json([
'status' => false,
'message' => '房間狀態有誤',
'redirect_uri' => route('room.chat', ['id' => $id]),
]);
}
$this->message->create(
[
'user_id' => Auth::user()->id,
'room_id' => $id,
'date' => Carbon::now()->toDateString(),
'content' => $request->get('content'),
]
);
broadcast((new RoomMessageChannelEvent(['user' => Auth::user(), 'content' => $request->get('content')], $id)));
return response()->json([
'status' => true,
'message' => null,
]);
}
}
app\event\RoomMessageChannelEvent
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Arr;
use Carbon\Carbon;
/**
* Class RoomMessageChannelEvent
*
* @package App\Events\Rooms
* @Author: Roy
* @DateTime: 2021/10/21 下午 02:34
*/
class RoomMessageChannelEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public $room_id;
/**
* RoomMessage constructor.
*
* @param $message
* @param $room_id
*
* @Author: Roy
* @DateTime: 2021/10/21 上午 11:54
*/
public function __construct($message, $room_id)
{
$this->room_id = $room_id;
$this->message = (object) [
'user' => (object) [
'id' => Arr::get($message, 'user.id'),
'name' => Arr::get($message, 'user.name'),
'image' => sprintf("https://ui-avatars.com/api/?name=%s&color=7F9CF5&background=EBF4FF",
Arr::get($message, 'user.name')),
],
'content' => Arr::get($message, 'content'),
'time' => Carbon::now()->format('H:i'),
];
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PresenceChannel(sprintf("chat.%s", $this->room_id));
}
}
javescript 使用laravel.echo,jquery,mustache
啟動websocket(預設port:6001)
# 預設port:6001
php artisan websockets:serve
//php artisan websockets:serve --port=6001
範例畫面
github範本 :
https://github.com/cc711612/chat_room
範本 :
參考文獻:
https://beyondco.de/docs/laravel-websockets/getting-started/introduction
https://learnku.com/docs/laravel/8.x/broadcasting/9388#presence-channels
No Comment!
Join Us Discuss