文章转发自专业的Laravel开发者社区,原文链接:https://learnku.com/laravel/t...LaravelNotification是在5.3版中作为核心框架的扩展添加。它为我们提供了一个通俗易懂、表现力强的API来发送通知,包括各种预设的发送通道和Laravel社区提供的各种自定义通道。其中一个重要的渠道是数据库通知,通知消息数据存储在数据库中。下面是一个简单的例子,假设我们有一个InvitationNotification类,它有一个toArray方法来生成通知消息的标题和详细信息:sender=$sender;$this->invitation=$invitation;}publicfunctionvia($notifiable){return[FCMChannel::class,'database'];}publicfunctiontoArray($notifiable){return['title'=>trans('notifications.new_invitation_title'),'details'=>trans('notifications.new_invitation_details',['sender'=>$this->sender->full_name,'receiver'=>$notifiable->full_name,'relation'=>$this->invitation->relation->name,'invitation'=>trans("mobile.invitation")])];}}Bottleneck从前面的代码可以看出,Laravel的数据库通道toArray或者toDatabase方法生成的通知消息数据会提前存储到数据库中,在一些项目中可能会用到,但是还是有一些限制:如果有多种语言,用户可以随意选择切换语言,我们怎么做呢?用英文显示标题和详细信息,用阿拉伯语显示另一个?通知消息动态变化怎么办?比如生日提醒“今天是李四生日”,第二天的通知内容应该改为“昨天是李四生日”等等。当用户收藏帖子时,帖子的创建者将收到通知“Janedoe喜欢你的帖子”,而另一个用户收藏了该帖子,创建者将收到“Jon和Jane喜欢你的帖子”。为了支持多国语言,我尝试将key和parameters的对应关系存储在数据库中,在读取通知数据时使用trans函数转换title和details。但问题是传输的参数可能还需要重新翻译。此外,我们不能仅仅通过创建新通知或更新当前通知的内容来进行这些更改。解决方案当我在试图找出解决这个问题的最佳方法时遇到困难时,我有了另一个想法并构建了这个扩展。此解决方案依赖于覆盖DatabaseChannel以将通知数据存储为序列化通知对象,而不是存储键和值数组。routeNotificationFor('数据库',$notification)->create($this->buildPayload($notifiable,$notification));}/***获取通知的数据。**@parammixed$notifiable*@param\Illuminate\Notifications\Notification$notification**@throws\RuntimeException**@returnNotification*/protectedfunctiongetData($notifiable,Notification$notification){返回$通知;}/***为DatabaseNotification模型构建一个数组负载。**@parammixed$notifiable*@param\Illuminate\Notifications\Notification$notification**@return数组*/protectedfunctionbuildPayload($notifiable,Notification$notification){return['id'=>$notification->id,'type'=>get_class($notification),'data'=>['data'=>serialize($this->getData($notifiable,$notification))],'read_at'=>null,'serialized'=>真];}}我还重写了DatabaseNotification模型,为数据字段添加了accessor,这样数据序列化后就可以返回Serialize,然后提取notification对象,最后调用toDatabase或者toArray方法得到最终的输出attributes['data'];}如果(isset($this->attributes['serialized'])&&$this->attributes['serialized']){$obj=unserialize($data['data']);如果(method_exists($obj,'toDatabase')){return$obj->toDatabase($this->notifiable);}else{return$obj->toArray($this->notifiable);}}else{返回$data;}}}优点通过使用这种方式,所有构造通知的代码都被移动到toDatabase或toArray方法中进行处理。reactive-notification安装方法composer需要digitalcloud/reactive-notification发布和迁移phpartisanvendor:publishprovider="Digitalcloud\ReactiveNotification\ReactiveNotificationServiceProvider"phpartisanmigrate使用方法更改模型中使用的特征从IlluminateNotificationsNotifiable到DigitalcloudNotificationApp;Digitalcloud\ReactiveNotification\Traits\Notifiable;使用Illuminate\Foundation\Auth\User作为Authenticatable;classUserextendsAuthenticatable{useNotifiable;}2.从从数据库数据库更改传递方法或者或者或者或者或者chchchchch类InvoicePaid扩展通知实现ShouldQueue{使用Queueable;公共功能通过($notifiable){返回[DatabaseChannel::class,'.../'];}publicfunctiontoDatabase($notifiable){return["title"=>trans("invoice_title"),"details"=>trans("invoice_details"),];}}示例翻译:notify(newInvoicePaid($invoice));\App::setLocale("en");$result=$user->notifications()->first()->数据;//结果将是["title"=>"Invoicetitle","details"=>"Invoicedetails"]\App::setLocale("ar");$result=$user->notifications()->first()->数据;//resultwillbe["title"=>"?????????????","details"=>"??????????????"]内容动态变化:member=$member;}}publicfunctionvia(){return[DatabaseChannel::class];}publicfunctiontoArray($notifiable){$date=Carbon::parse($this->member->birthday)->format("m-d");if(today()->format("m-d")==$date){$details=trans_choice('notifications.birth_day_today',$this->member->gender,['name'=>$this->member->名称]);}elseif(today()->subDay()->format("m-d")==$date){$details=trans_choice('notifications.birth_day_yesterday',$this->member->gender,['name'=>$this->成员->姓名]);}else{$details=trans_choice('notifications.birth_day_old',$this->member->gender,['name'=>$this->member->name,"date"=>$date]);}return['title'=>trans('notifications.birth_day_title'),'details'=>$细节];}}$user->notify(newBirthDayNotification($member));$notification=$user->notifications()->first();如果一个成员的生日是今天,结果消息是“今天是约翰的生日,祝他生日快乐!”如果成员的生日是昨天,最后的消息将更改为“John昨天庆祝了他的生日”Carbon::setTestNow(now()->addDay());最后,如果成员的生日是特定日期,则最终消息将更改为“JohncelebratedhisbirthdayonDecember31st”。Carbon::setTestNow(now()->addMonths(3));希望您喜欢使用此软件包并从列出的详细信息中受益。请继续关注有关高级Laravel通知的其他故事。
