neoan.io/broadcast

该软件包最新版本(v0.1.0)没有可用的许可证信息。

使用简化版的socket.io广播

安装: 5

依赖项: 0

建议者: 0

安全性: 0

星标: 0

关注者: 1

分支: 0

开放性问题: 0

语言:JavaScript

类型:软件包

v0.1.0 2023-01-20 23:12 UTC

This package is auto-updated.

Last update: 2024-09-21 02:59:30 UTC


README

保持多个客户端与数据库同步!

专为 LENKRAD 设计,但足够通用,可在任何框架中使用。

使任何数据库都成为实时数据库

安装

1. 安装软件包

composer require neoan.io/broadcast

2. 将所需的ENV变量添加到您的.env文件中

  • JWT_SECRET(您的加密密钥)
  • SOCKET_SERVER_PORT(例如,3000)
  • SOCKET_SERVER_URL(例如,"localhost")

3. 将以下脚本添加到您的composer.json中

...
"scripts": {
  "install-socket": "NeoanIo\\MarketPlace\\Broadcast\\NpmHandler::package"
}
...

4. 运行脚本

composer run install-socket

5. 安装所需的node软件包

yarn installnpm install

6. 测试socket服务器

yarn sockert-servernpm run socket-server

设置

客户端功能

此软件包包含一个客户端库,用于自动与数据库同步。在 LENKRAD 中,您通常会通过路由公开此库

<?php

namespace App\Socket;

use Neoan\Routing\Attributes\Get;
use Neoan\Routing\Interfaces\Routable;
use NeoanIo\MarketPlace\Broadcast\ForClient;

// exposes the client-library to the path /client.js
#[Get('/client.js')]
class Client implements Routable
{
    public function __invoke(): void
    {
        // This will deliver a generated JS-file 
        ForClient::exposeClient();
    }
}

然后在前端使用所需的任何功能

<script type="module" async>
    import {SyncEntity, HTMLBinder} from "/client.js";
</script>

后端

为了让同步工作,需要发生两件事。首先,返回的实体必须公开socket信息(包括身份验证)。我们可以使用 ForClient::wrapEntity 来实现这一点。典型的API路由可能如下所示

<?php

namespace App\Note;

use Neoan\Request\Request;
use Neoan\Routing\Attributes\Get;
use Neoan\Routing\Interfaces\Routable;
use NeoanIo\MarketPlace\Broadcast\ForClient;

#[Get('/api/note/:id')]
class GetNote implements Routable
{
    public function __invoke(): array
    {
        // retrieving a single record
        $model = NoteModel::get(Request::getParameter('id'));

        // wrapping the record 
        return ForClient::wrapEntity($model->toArray())
            ->toRoom('notes')
            ->withId($model->id)
            ->broadcast();

    }
}

接下来,我们希望在模型被写入时设置一个钩子。在 LENKRAD 中,我们可以使用 Model::afterStore 方法来实现。我们的Note模型可能如下所示

<?php

namespace App\Note;

use NeoanIo\MarketPlace\Broadcast\Broadcast;
use Neoan\Model\Attributes\IsPrimaryKey;
use Neoan\Model\Attributes\Type;
use Neoan\Model\Model;

class NoteModel extends Model
{
    #[IsPrimaryKey]
    public int $id;

    #[Type('MEDIUMTEXT')]
    public string $content;

    // will fire whenever the model is saved to the database
    protected function afterStore(): void
    {
        // this broadcasts updates to the socket server
        Broadcast::toChannel('notes')
            ->withId($this->id)
            ->withBody($this->toArray())
            ->emit();
    }

}

我们不必在更新路由中担心任何特定的代码。根据示例,它可能如下所示

<?php

namespace App\Note;

use Neoan\Request\Request;
use Neoan\Routing\Attributes\Put;
use Neoan\Routing\Interfaces\Routable;

#[Put('/api/note/:id')]
class PutNote implements Routable
{
    public function __invoke(): NoteModel
    {
        $find = NoteModel::get(Request::getParameter('id'));
        $find->content = Request::getInput('content');
        return $find->store();
    }
}

前端使用

// taken from earlier example
import {SyncEntity, HTMLBinder} from "/client.js";

// allow for programmatic updates on any change (without event)
// careful: this produces a lot of traffic and is usually not necessary)
let updateOnAnyChange = true;

// SyncEntity grabs the wrapped entity via GET
// (the PUT-request needs ot be in the same format)
// SyncEntity returns a proxy triggering PUT-requests as needed,
// and receiving updates via socket alike!
let note = await SyncEntity('/api/note/1', updateOnAnyChange)

// if `updateOnAnyChange` is true, every change will be broadcasted
setTimeout(()=> {
    note.content += '!';
    updateOnAnyChange = false;
}, 1000)

// however, we usually want to trigger on specific events
const binder = new HTMLBinder(note)
// e.g. on form submission

binder.toForm('#my-form')

// or directly on the element-level

binder.toElements({
    '#my-input':{
        property: 'content',
        event: 'blur'
    }
})

鸣谢

代理逻辑基于Sindre Sorhus修改的版本 on-change。请确保留下星标 ;-)