Laravel:自定义或扩展通知 - 数据库模型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43646085/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel: customize or extend notifications - database model
提问by BassMHL
IMHO, the current Database channel for saving notifications in Laravel is really bad design:
恕我直言,当前用于在 Laravel 中保存通知的数据库通道设计非常糟糕:
- You can't use foreign key cascades on items for cleaning up notifications of a deleted item for example
- Searching custom attributes in the
data
column (casted to Array) is not optimal
- 例如,您不能在项目上使用外键级联来清理已删除项目的通知
- 在
data
列中搜索自定义属性(转换为数组)不是最佳选择
How would you go about extending the DatabaseNotification
Model in vendor package?
您将如何DatabaseNotification
在供应商包中扩展模型?
I would like to add columns event_id
, question_id
, user_id
(the user that created the notification) etc... to the default laravel notifications
table
我想添加列event_id
,question_id
,user_id
(在创建该通知用户)等等为默认laravelnotifications
表
How do you override the send
function to include more columns?
您如何覆盖该send
函数以包含更多列?
In:
在:
vendor/laravel/framework/src/Illuminate/Notifications/Channels/DatabaseChannel.php
The code:
编码:
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,
]);
}
}
回答by BassMHL
To create a custom Notification Channel:
要创建自定义通知渠道:
First, create a Class in App\Notifications for example:
首先,在 App\Notifications 中创建一个类,例如:
<?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,
]);
}
}
Second, use this channel in the via
method in the Notification class:
其次,via
在Notification类的方法中使用这个通道:
<?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
];
}
}
回答by Kamal Khan
Create and use your own Notification
model and Notifiable
trait and then use your own Notifiable trait in your (User) models.
创建并使用您自己的Notification
模型和Notifiable
特征,然后在您的(用户)模型中使用您自己的 Notifiable 特征。
App\Notifiable.php:
应用\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');
}
}
App\Notification.php:
应用\Notification.php:
namespace App;
use Illuminate\Notifications\DatabaseNotification;
class Notification extends DatabaseNotification
{
// ...
}
App\User.php:
应用\用户.php:
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
// ...
}
回答by cweiske
Unlike "Bassem El Hachem", I wanted to keep the database
keyword in the via()
methods.
与“Bassem El Hachem”不同,我想database
在via()
方法中保留关键字。
So in addition to a custom DatabaseChannel
, I also wrote my own ChannelManager
that returns my own DatabaseChannel
in the createDatabaseDriver()
method.
所以除了自定义之外DatabaseChannel
,我还编写了自己的ChannelManager
,DatabaseChannel
在createDatabaseDriver()
方法中返回我自己的。
In my apps' ServiceProvider::register()
method, I overwrote the singleton for the original ChannelManager class to return my custom manager.
在我的应用程序的ServiceProvider::register()
方法中,我覆盖了原始 ChannelManager 类的单例以返回我的自定义管理器。
回答by Samuel Martins
An example for @cweiske response.
If you really need extends the Illuminate\Notifications\Channels\DatabaseChannel
not creating a new Channel you can:
如果您确实需要扩展Illuminate\Notifications\Channels\DatabaseChannel
不创建新频道,您可以:
Extends the channel:
扩展通道:
<?php
namespace App\Notifications;
use Illuminate\Notifications\Channels\DatabaseChannel as BaseDatabaseChannel;
use Illuminate\Notifications\Notification;
class MyDatabaseChannel extends BaseDatabaseChannel
{
/**
* Send the given notification.
*
* @param mixed $notifiable
* @param \Illuminate\Notifications\Notification $notification
* @return \Illuminate\Database\Eloquent\Model
*/
public function send($notifiable, Notification $notification)
{
$adminNotificationId = null;
if (method_exists($notification, 'getAdminNotificationId')) {
$adminNotificationId = $notification->getAdminNotificationId();
}
return $notifiable->routeNotificationFor('database')->create([
'id' => $notification->id,
'type' => get_class($notification),
'data' => $this->getData($notifiable, $notification),
// ** New custom field **
'admin_notification_id' => $adminNotificationId,
'read_at' => null,
]);
}
}
And register the Illuminate\Notifications\Channels\DatabaseChannel
on application container again:
并Illuminate\Notifications\Channels\DatabaseChannel
再次注册应用程序容器:
app\Providers\AppServiceProvider.php
app\Providers\AppServiceProvider.php
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(
Illuminate\Notifications\Channels\DatabaseChannel::class,
App\Notifications\MyDatabaseChannel::class
);
}
}
Now when the Illuminate\Notifications\ChannelManager
try createDatabaseDriver
will return your registered database driver.
现在Illuminate\Notifications\ChannelManager
尝试createDatabaseDriver
将返回您注册的数据库驱动程序。
More one option to solve this problem!
解决这个问题的更多选择!
回答by Luca C.
I solved a similar problem by customizing notification class:
我通过自定义通知类解决了类似的问题:
create the class for this action:
为此操作创建类:
artisan make:notification NewQuestion
inside it:
在里面:
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;
}
then you can access proper data in view or controller like this:
然后您可以像这样在视图或控制器中访问正确的数据:
@if($notification->type=='App\Notifications\UserRegistered')
<a href="{!!route('question.show',$notification->data['question']['id'])!!}">New question from {{$notification->data['user']['name']}}</a>
@endif