序言
感谢Marcel Pociot等人为Laravel优秀的包做出了巨大贡献。感谢DevMarketer提供的详细步骤。
然而...
所以,我已经很长时间想尝试使用Laravel Echo和Pusher来实现广播和实时通知。但由于主要在开发不依赖外部服务的内部应用,所以我倒霉透顶了。自从Marcel在2021年Laracon Online Winter上关于“理解Laravel广播”的精彩演讲后,我就迫不及待地想深入学习这个话题。
所以,我打开了新的终端窗口,输入laravel new websockets
(用于创建新的Laravel应用),并跟随https://beyondco.de/docs/laravel-websockets/中提供的详细步骤。
我不知道我在哪里出了问题,但一切都没有按预期工作。结果是我本地的Valet和自签名SSL证书设置出了问题(2021年了,谁还用HTTP呢,对吧?)
所以,这里是我的指南,介绍了如何在Valet和SSL的帮助下运行自己的本地WebSockets服务器。
让我们开始吧!
先决条件
我正在运行Laravel Valet 2.14.1和PHP 8.0.3
设置
从头开始,我们将创建一个新的Laravel项目(本文撰写时为Laravel 8.36.2)
$ laravel new websockets
需要一个全新的SSL证书吗?
$ cd websockets
$ valet secure
Restarting nginx...
The [websockets.test] site has been secured with a fresh TLS certificate.
让我们更改.env
文件中应用的URL
APP_URL=https://websockets.test
我们需要拉取beyondcode/laravel-websockets包
composer require beyondcode/laravel-websockets
现在让我们发布迁移(用于统计)和配置文件
$ php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
让我们发布WebSocket配置文件
$ php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
运行迁移(您应该先设置数据库并相应地更新 .env文件)
$ php artisan migrate
配置
我们现在准备开始,让我们看看我们的配置文件。首先,我们需要更改.env中的BROADCAST_DRIVER
...
BROADCAST_DRIVER=pusher
...
PUSHER_APP_ID=1 // this can be anything you want
PUSHER_APP_KEY=some-key // this can also be anything you want
PUSHER_APP_SECRET=some-secret // also this
PUSHER_APP_CLUSTER=mt1 // doesn't matter
"为什么是pusher
?"你可能这么问。我不想用外部服务,对吧?你说得对,我们实际上并没有使用pusher。因为laravel-websockets
使用与pusher相同的API,所以我们在使用pusher
驱动程序。
现在,在config/broadcasting.php
中找到connections
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
'host' => '127.0.0.1', // add this
'port' => 6001, // and this
'encrypted' => true, // also this
'scheme' => 'https', // and this
'curl_options' => [ // since we're only doing stuff locally this is fine
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
],
],
几乎完成了!让我们看看config/websockets.php
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
我们需要在.env
中设置这些环境变量以使SSL正常工作。
在.env
中添加以下条目
LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT=/absolute/path/to/your/crt/file
LARAVEL_WEBSOCKETS_SSL_LOCAL_PK=/absolute/path/to/your/key/file
根据您的设置,这些文件将 reside in ~/.config/valet/Certifificates
,在我的情况下,它看起来像这样
LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT=/Users/maze/.config/valet/Certificates/websockets.test.crt
LARAVEL_WEBSOCKETS_SSL_LOCAL_PK=/Users/maze/.config/valet/Certificates/websockets.test.key
现在我们准备好使用以下命令启动WebSocket服务器
$ php artisan websockets:serve
如果一切顺利,你应该在你的终端中看到以下输出
Starting the WebSocket server on port 6001...
打开浏览器,转到位于https://websockets.test/laravel-websockets
的WebSocket仪表板,并单击Connect
。
你应该看到一些类型为subscribed
的事件,这意味着服务器正在运行。您的终端也将充满了调试信息。
太棒了对吧?但是等等,还有更多!我们能不能将前端连接起来,每当我们分派一个事件时都会弹出警告窗口?这将非常烦人,但为了示例,足够了。
前端
我们需要拉入两个NPM包
$ npm install --save-dev laravel-echo pusher-js
又是Pusher包?好吧,是的,同一个API,还记得吗?
现在让我们在resources/js/bootstrap.js
中设置Laravel Echo
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,
forceTLS: true,
wsHost: window.location.hostname,
wssPort: 6001,
});
编译你的前端资源
$ npm run dev
因为我们使用的是纯净的Laravel安装,所以我们只需向位于resources/views/welcome.blade.php
的欢迎视图中添加一些JS即可
<script src="{{ mix('js/app.js') }}"></script>
<script>
Echo.channel('home')
.listen('Message', (e) => alert(e.message));
</script>
</body>
</html>
这将监听home频道,并将事件广播到该频道时显示消息。说到事件,我们还需要创建一个,所以
$ php artisan make:event Message
app/Events/Message.php
应该像这样
<?php
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;
class Message implements ShouldBroadcast // this needs to be added
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message; // our message
public function __construct(string $message)
{
$this->message = $message;
}
public function broadcastOn()
{
return new Channel('home');
}
}
这个事件将在分派后通过home
频道广播,并且Laravel Echo将监听这个事件被分派。
现在,打开一个浏览器窗口,将其指向本地应用程序的索引页面,位于https://websockets.test
,你应该看到欢迎页面。
在您的终端中打开Laravel Tinker。我们使用Tinker来快速分派事件,而无需编写大量的应用程序逻辑。
$ php artisan tinker
Psy Shell v0.10.8 (PHP 8.0.3 — cli) by Justin Hileman
>>>
然后手工启动事件
$ php artisan tinker
Psy Shell v0.10.8 (PHP 8.0.3 — cli) by Justin Hileman
>>> App\Events\Message::dispatch('this is awesome')
现在,当你按下回车键时,事件将被分派,你应该在浏览器中看到一个警告弹出。我们完成了!这不很难,不是吗?
下一步是什么?
你可以在https://github.com/mazedlx/laravel-websockets-example查看这个示例的代码。
别忘了看看https://pusher.com/和https://ably.com/,他们都提供了慷慨的免费计划。
还可以访问https://github.com/beyondcode/laravel-websockets并给仓库点赞,关注https://twitter.com/marcelpociot。
如果您想查看一个现实生活中的示例,我的好朋友Christoph Rumpel不久前写了一篇关于使用Laravel Websockets包实现实时通知的博客文章。
drivesvints喜爱这篇文 章