恕我直言,在Laravel保存通知当前数据库通道是非常糟糕的设计:
- 不能使用上的项目外键级联清理例如已删除项目的通知
- 搜索定制在属性
data
列(浇铸阵列)不是最佳的
你会如何去延长DatabaseNotification
在供应商的套餐模式?
我想补充列event_id
, question_id
, user_id
等(创建该通知的用户)......到默认laravel notifications
表
你如何重写send
功能,包括多列?
在:
vendor/laravel/framework/src/Illuminate/Notifications/Channels/DatabaseChannel.php
代码:
class DatabaseChannel
{
/**
* Send the given notification.
*
* @param mixed $notifiable
* @param \Illuminate\Notifications\Notification $notification
* @return \Illuminate\Database\Eloquent\Model
*/
public function send($notifiable, Notification $notification)
{
return $notifiable->routeNotificationFor('database')->create([
'id' => $notification->id,
'type' => get_class($notification),
\\I want to add these
'user_id' => \Auth::user()->id,
'event_id' => $notification->type =='event' ? $notification->id : null,
'question_id' => $notification->type =='question' ? $notification->id : null,
\\End adding new columns
'data' => $this->getData($notifiable, $notification),
'read_at' => null,
]);
}
}
要创建自定义通知信道:
首先,在应用程序\通知例如A类:
<?php
namespace App\Notifications;
use Illuminate\Notifications\Notification;
class CustomDbChannel
{
public function send($notifiable, Notification $notification)
{
$data = $notification->toDatabase($notifiable);
return $notifiable->routeNotificationFor('database')->create([
'id' => $notification->id,
//customize here
'answer_id' => $data['answer_id'], //<-- comes from toDatabase() Method below
'user_id'=> \Auth::user()->id,
'type' => get_class($notification),
'data' => $data,
'read_at' => null,
]);
}
}
第二,在使用此信道via
在通知类方法:
<?php
namespace App\Notifications;
use Illuminate\Notifications\Notification;
use App\Notifications\CustomDbChannel;
class NewAnswerPosted extends Notification
{
private $answer;
public function __construct($answer)
{
$this->answer = $answer;
}
public function via($notifiable)
{
return [CustomDbChannel::class]; //<-- important custom Channel defined here
}
public function toDatabase($notifiable)
{
return [
'type' => 'some data',
'title' => 'other data',
'url' => 'other data',
'answer_id' => $this->answer->id //<-- send the id here
];
}
}
创建和使用自己的Notification
模型和Notifiable
特征,然后使用自己的法定特质在你(用户)模式。
应用程序\ Notifiable.php:
namespace App;
use Illuminate\Notifications\Notifiable as BaseNotifiable;
trait Notifiable
{
use BaseNotifiable;
/**
* Get the entity's notifications.
*/
public function notifications()
{
return $this->morphMany(Notification::class, 'notifiable')
->orderBy('created_at', 'desc');
}
}
应用程序\ Notification.php:
namespace App;
use Illuminate\Notifications\DatabaseNotification;
class Notification extends DatabaseNotification
{
// ...
}
应用程序\ user.php的:
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
// ...
}
在我看来laravel通知是notyet准备和非常有限的功能。
不管怎样,我通过自定义通知类解决了类似的问题:
创建此操作的类:
artisan make:notification NewQuestion
在里面:
public function __construct($user,$question)
{
$this->user=$user;
$this->question=$question;
}
...
public function toDatabase($notifiable){
$data=[
'question'=>$this->(array)$this->question->getAttributes(),
'user'=>$this->(array)$this->user->getAttributes()
];
return $data;
}
那么你就可以访问视图或控制器这样的正确的数据:
@if($notification->type=='App\Notifications\UserRegistered')
<a href="{!!route('question.show',$notification->data['question']['id'])!!}">New question from {{$notification->data['user']['name']}}</a>
@endif
与“厄尔尼诺的Bassem哈希姆”,我想保持database
的关键字中via()
方法。
所以除了自定义DatabaseChannel
,我也写了我自己的ChannelManager
返回自己DatabaseChannel
在createDatabaseDriver()
方法。
在我的应用程序ServiceProvider::register()
方法中,我改写为原ChannelManager类返回我的自定义管理器中的单。