Filament 数据库通知(Database Notifications)实战指南:在 Laravel 面板中发送、接收与标记已读
Filament 数据库通知Database Notifications实战指南在 Laravel 面板中发送、接收与标记已读【免费下载链接】filamentA powerful open-source UI framework for Laravel • Build and ship apps admin panels fast with Livewire项目地址: https://gitcode.com/GitHub_Trending/fi/filament数据库通知Database Notifications是 Filament 面板内置的持久化通知能力通知以记录形式写入数据库用户可在面板顶栏或侧边栏的铃铛触发器中查看、分页浏览、标记已读或清除。本文以 Filament 仓库中 packages/notifications/docs/02-database-notifications.md 为主体结合packages/notifications、packages/panels与packages/actions的源码实现完整讲解数据库通知的建表、面板启用、多种发送方式、实时接收轮询与 WebSocket、已读/未读标记以及弹窗手动打开等全流程方案。读完本文你可以在自己的 Filament 面板中落地一套从“落库”到“实时触达”的完整通知系统。一、准备 notifications 数据表在启用任何数据库通知功能之前需要先确保 Laravel 的 notifications 表已存在于数据库中。Filament 直接复用 Laravel 原生的通知表结构执行以下 Artisan 命令即可生成迁移文件并创建表php artisan make:notifications-table该迁移会创建notifications表包含id、type、notifiable多态关联、dataJSON 存储通知载荷、read_at已读时间戳以及created_at/updated_at等字段。在 Filament 的演示应用中对应的迁移位于 docs-assets/app/database/migrations/2023_07_02_122748_create_notifications_table.php可作为真实参考。针对两种特殊数据库环境官方文档给出了两条明确的调优建议使用 PostgreSQL 时确保迁移中的data列使用json()类型即$table-json(data)以保证通知数据以 JSON 语义存储与查询Filament 在查询通知时会使用data-format这类 JSON 路径条件。User模型使用 UUID 主键时确保notifiable列使用uuidMorphs()即$table-uuidMorphs(notifiable)避免多态关联类型/ID 与字符串主键不匹配。二、在面板中启用数据库通知若希望面板中出现数据库通知的铃铛触发器需在面板的panel()方法中链式调用databaseNotifications()。参考 docs/05-panel-configuration.md 中的面板配置方式use Filament\Panel; public function panel(Panel $panel): Panel { return $panel // ... -databaseNotifications(); }从 packages/panels/src/Panel/Concerns/HasNotifications.php 的源码可以看到该方法实际签名支持多个可选参数用于更精细的控制public function databaseNotifications( bool | Closure $condition true, string | Closure | null $livewireComponent null, bool | Closure $isLazy true, DatabaseNotificationsPosition | Closure | null $position null, ): static各参数含义如下参数默认值说明$conditiontrue是否启用数据库通知支持传入闭包做运行时判断$livewireComponentnull自定义的 Livewire 组件类名默认使用Filament\Livewire\DatabaseNotifications$isLazytrue是否懒加载通知组件默认懒加载可显著减少首屏开销$positionnull触发器位置传入DatabaseNotificationsPosition枚举null时按顶栏是否存在自动回退此外还有独立的databaseNotificationsPolling(string | Closure | null $interval)方法用于配置轮询间隔具体见下文“轮询”小节。三、发送数据库通知Filament 提供了多种发送方式你可以按场景选择最合适的一种。方式一流式 APIsendToDatabase()使用 Filament 的流式fluentAPI 构造通知并直接写入接收者的通知表中use Filament\Notifications\Notification; $recipient auth()-user(); Notification::make() -title(Saved successfully) -sendToDatabase($recipient);从源码 packages/notifications/src/Notification.php 看sendToDatabase()的实现是对传入的用户支持单个用户也支持Collection或数组批量逐个调用$user-notify($this-toDatabase())因此其底层仍然是 Laravel 的Notifiable通知机制。方式二notify()方法 toDatabase()如果你希望完全走 Laravel 原生调用链可以先在Notification上调用toDatabase()获得一个数据库通知实例再通过接收者的notify()发送use Filament\Notifications\Notification; $recipient auth()-user(); $recipient-notify( Notification::make() -title(Saved successfully) -toDatabase(), );重要队列前提。Laravel 默认通过队列发送数据库通知。从 packages/notifications/src/DatabaseNotification.php 可以看到DatabaseNotification类实现了ShouldQueue并使用Queueabletrait即通知发送会被投递到队列。因此请确保你的队列 Worker 正在运行如php artisan queue:work否则通知不会真正落库。方式三传统 Laravel 通知类 getDatabaseMessage()如果你已经使用了传统的 Laravel 通知类只需让它的toDatabase()方法返回 Filament 通知的数据库载荷即可use App\Models\User; use Filament\Notifications\Notification; public function toDatabase(User $notifiable): array { return Notification::make() -title(Saved successfully) -getDatabaseMessage(); }这里的关键是getDatabaseMessage()方法packages/notifications/src/Notification.php它会将通知序列化为数组并做三件事设置duration persistent——数据库通知在弹窗中不会自动消失需要用户手动关闭或标记已读设置format filament——这是 Filament 识别自己通知的标记移除id——因为落库后通知记录自身的id才是唯一标识。与之对应面板侧的查询会使用where(data-format, filament)过滤出属于 Filament 的通知见 packages/notifications/src/Livewire/DatabaseNotifications.php而读取时通过Notification::fromDatabase()依据data载荷还原通知实例并将其id替换为数据库记录主键。四、将通知触发器移动到侧边栏默认情况下数据库通知的铃铛触发器位于面板顶栏topbar如果顶栏被禁用触发器会自动落入侧边栏sidebar。如果你希望始终将其放在侧边栏可以通过databaseNotifications()的position参数显式指定use Filament\Enums\DatabaseNotificationsPosition; use Filament\Panel; public function panel(Panel $panel): Panel { return $panel // ... -databaseNotifications(position: DatabaseNotificationsPosition::Sidebar); }DatabaseNotificationsPosition是一个字符串枚举packages/panels/src/Enums/DatabaseNotificationsPosition.php仅有两个取值枚举值字符串值含义DatabaseNotificationsPosition::Topbartopbar触发器位于顶栏DatabaseNotificationsPosition::Sidebarsidebar触发器位于侧边栏从 packages/panels/src/Panel/Concerns/HasNotifications.php 的getDatabaseNotificationsPosition()实现可以看出默认回退逻辑未显式设置时若面板存在顶栏则用Topbar否则用Sidebar——这与官方文档的描述完全一致。五、接收数据库通知在不做任何额外设置的情况下新通知只会在页面首次加载时被拉取。若要实现新通知的持续感知有以下两种机制可任选其一。5.1 轮询Polling轮询是指客户端周期性向服务器发起请求以检查新通知。优点是实现简单、无需额外基础设施缺点是会增加服务器负载在高并发场景下不够“优雅”。Filament 默认每30 秒轮询一次。若需调整间隔使用databaseNotificationsPolling()use Filament\Panel; public function panel(Panel $panel): Panel { return $panel // ... -databaseNotifications() -databaseNotificationsPolling(30s); }传入null可完全禁用轮询use Filament\Panel; public function panel(Panel $panel): Panel { return $panel // ... -databaseNotifications() -databaseNotificationsPolling(null); }源码层面轮询间隔的默认值30s在面板 trait 与 Livewire 组件中均有体现packages/panels/src/Panel/Concerns/HasNotifications.php 中$databaseNotificationsPolling 30spackages/notifications/src/Livewire/DatabaseNotifications.php 中public static ?string $pollingInterval 30s。Livewire 轮询时长支持 Laravel 的间隔语法如5s、2m。5.2 使用 Echo 与 WebSocket 实时接收WebSocket 是更高效的实时方案。首先需要在面板中完成 WebSocket 基础设施配置参见 packages/notifications/docs/03-broadcast-notifications.md 的“Setting up websockets in a panel”一节本质是配置broadcastConnector等连接参数。配置完成后发送通知时只需将isEventDispatched参数设为true即可自动派发DatabaseNotificationsSent事件前端监听到该事件后会立即拉取最新通知实现接近实时的触达use Filament\Notifications\Notification; $recipient auth()-user(); Notification::make() -title(Saved successfully) -sendToDatabase($recipient, isEventDispatched: true);事件机制可以从源码得到完整印证sendToDatabase()在$isEventDispatched为true时对每个接收者调用DatabaseNotificationsSent::dispatch($user)packages/notifications/src/Notification.phpDatabaseNotificationsSent是一个实现ShouldBroadcast的事件类广播名称为database-notifications.sent广播通道为私有频道packages/notifications/src/Events/DatabaseNotificationsSent.php。频道命名规则是若用户模型定义了receivesBroadcastNotificationsOn()方法则使用其返回值否则使用{用户类名中的反斜杠替换为点}.{用户主键}例如App.Models.User.1前端 Livewire 组件通过#[On(databaseNotificationsSent)]监听该事件并触发refresh()方法重新拉取通知packages/notifications/src/Livewire/DatabaseNotifications.php。5.3 通知列表的分页与加载从 packages/notifications/src/Livewire/DatabaseNotifications.php 可以看到通知列表默认启用分页每页simplePaginate(50)分页参数名为database-notifications-page。同时组件默认是懒加载的$isLazy true配合placeholder()中渲染的触发器可以在用户真正打开弹窗前不加载全部通知数据。六、标记数据库通知为已读 / 未读在数据库通知弹窗的顶部有一个“全部标记为已读”按钮对应源码中的markAllNotificationsAsReadAction()packages/notifications/src/Livewire/DatabaseNotifications.php其底层执行getUnreadNotificationsQuery()-update([read_at now()])。此外还提供“清除全部”操作clearNotificationsAction()会删除当前用户所有 Filament 通知记录。若要标记单条通知可参考 packages/notifications/docs/01-overview.md 中“Adding actions to notifications”一节为通知挂载 Action并在 Action 上调用markAsRead()use Filament\Actions\Action; use Filament\Notifications\Notification; Notification::make() -title(Saved successfully) -success() -body(Changes to the post have been saved.) -actions([ Action::make(view) -button() -markAsRead(), ]) -sendToDatabase($recipient);同理使用markAsUnread()可将通知标记为未读use Filament\Actions\Action; use Filament\Notifications\Notification; Notification::make() -title(Saved successfully) -success() -body(Changes to the post have been saved.) -actions([ Action::make(markAsUnread) -button() -markAsUnread(), ]) -sendToDatabase($recipient);这些 Action 方法定义于 packages/actions/src/Action.php二者均接受bool | Closure参数默认为true可用于条件化标记。前端点击后会派发markedNotificationAsRead/markedNotificationAsUnread浏览器事件由 Livewire 组件监听并更新read_at字段packages/notifications/src/Livewire/DatabaseNotifications.php。七、从任意位置打开通知弹窗数据库通知弹窗本质上是一个 Livewire 模态框你可以通过派发open-modal浏览器事件从页面任意位置自定义按钮、菜单项等打开它button x-data{} x-on:click$dispatch(open-modal, { id: database-notifications }) typebutton Notifications /button注意其中的id: database-notifications是 Filament 约定的弹窗标识必须保持不变。八、测试与验证Filament 仓库为数据库通知提供了完整的测试覆盖参见 tests/src/Notifications/DatabaseNotificationsTest.php。测试中通过Notification::make()-title(Test)-sendToDatabase($this-user)模拟发送再断言通知是否落库、列表查询是否返回对应记录。这为你编写自己的通知测试提供了可直接借鉴的模式发送 → 查询 → 断言标题与状态。九、要点小结场景推荐做法关键源码位置建表php artisan make:notifications-tablePostgreSQL 用json()UUID 主键用uuidMorphs()docs-assets/app/database/migrations/2023_07_02_122748_create_notifications_table.php面板启用-databaseNotifications()packages/panels/src/Panel/Concerns/HasNotifications.php发送sendToDatabase()/notify(toDatabase())/ 传统通知类 getDatabaseMessage()packages/notifications/src/Notification.php位置position: DatabaseNotificationsPosition::Sidebarpackages/panels/src/Enums/DatabaseNotificationsPosition.php实时接收默认轮询30sWebSocket 方案开启isEventDispatched: truepackages/notifications/src/Events/DatabaseNotificationsSent.php已读/未读弹窗顶部“全部标记已读”Action 上调用markAsRead()/markAsUnread()packages/actions/src/Action.php手动打开派发open-modal事件id为database-notifications—数据库通知是 Filament 通知体系中最可靠、最容易上手的持久化方案它不依赖任何第三方推送服务数据落库即可审计回溯配合轮询或 WebSocket 事件又可以获得近乎实时的用户体验。在需要“离线可查、在线可达”的业务场景如订单状态变更、审核结果回执、系统告警中优先选择它往往是最稳妥的决策。【免费下载链接】filamentA powerful open-source UI framework for Laravel • Build and ship apps admin panels fast with Livewire项目地址: https://gitcode.com/GitHub_Trending/fi/filament创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考