创建通知
php artisan make:notification PrivateMessage
这条命令会在 app/Notifications 目录下生成一个新的通知类PrivateMessage。每个通知类都包含一个 via 方法以及一个或多个消息构建的方法(比如 toMail 或者 toDatabase),它们会针对指定的渠道把通知转换为对应的消息。
<?php namespace AppNotifications; use IlluminateBusQueueable; use IlluminateContractsQueueShouldQueue; use IlluminateNotificationsMessagesMailMessage; use IlluminateNotificationsNotification; class PrivateMessage extends Notification { use Queueable; /** * Create a new notification instance. * * @return void */ public function __construct() { // } /** * Get the notification's delivery channels. * * @param mixed $notifiable * @return array */ public function via($notifiable) { return ['mail']; } /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return IlluminateNotificationsMessagesMailMessage */ public function toMail($notifiable) { return (new MailMessage) ->line('The introduction to the notification.') ->action('Notification Action', url('/')) ->line('Thank you for using our application!'); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ // ]; } }
参考 Laravel 5.7 - New Notification System Tutorial for Beginner
可以在PrivateMessage的构造函数中,传入参数值。
修改如下:
<?php namespace AppNotifications; use IlluminateBusQueueable; use IlluminateContractsQueueShouldQueue; use IlluminateNotificationsMessagesMailMessage; use IlluminateNotificationsNotification; class PrivateMessage extends Notification { use Queueable; private $details; /** * Create a new notification instance. * * @return void */ public function __construct($details) { // $this->details = $details; } /** * Get the notification's delivery channels. * * @param mixed $notifiable * @return array */ public function via($notifiable) { return ['mail', 'database']; } /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return IlluminateNotificationsMessagesMailMessage */ public function toMail($notifiable) { // return (new MailMessage) // ->line('The introduction to the notification.') // ->action('Notification Action', url('/')) // ->line('Thank you for using our application!'); return (new MailMessage) ->greeting($this->details['greeting']) ->line($this->details['body']) ->action($this->details['actionText'], $this->details['actionURL']) ->line($this->details['thanks']); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ // ]; } /** * Get the array representation of the notification. * @param $notifiable * @return array */ public function toDatabase($notifiable) { return [ 'order_id' => $this->details['order_id'] ]; } }
因为需要toDatabase,那么需要建立一张表格来存储通知的数据:
php artisan notifications:table php artisan migrate
自动生成的数据库迁移文件如下:
<?php use IlluminateDatabaseMigrationsMigration; use IlluminateDatabaseSchemaBlueprint; use IlluminateSupportFacadesSchema; class CreateNotificationsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('notifications', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('type'); $table->morphs('notifiable'); $table->text('data'); $table->timestamp('read_at')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('notifications'); } }
注意:toArray方法或toDatabase方法中返回的值,会被自动转换为JSON格式然后存储到data字段中。【注意toArray方法和toDatabase方法的区别】
toArray 方法可以同时被 database 和 broadcast 渠道调用,如果你希望 database 和 broacast 两个渠道有不同的数组展现方式,你需要定义 toDatabase 或者 toBroadcast 以取代定义 toArray 方法。
如果需要通过控制器方式触发,可以新建一个控制器然后添加方法,并在route中添加一个路由,访问路由链接触发控制器中该发送通知的方法即可:
控制器:
<?php namespace AppHttpControllers; use IlluminateHttpRequest; use AppUser; use Notification; use AppNotificationsMyFirstNotification; class HomeController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth'); } /** * Show the application dashboard. * * @return IlluminateContractsSupportRenderable */ public function index() { return view('home'); } public function sendNotification() { $user = User::first(); $details = [ 'greeting' => 'Hi Artisan', 'body' => 'This is my first notification from ItSolutionStuff.com', 'thanks' => 'Thank you for using ItSolutionStuff.com tuto!', 'actionText' => 'View My Site', 'actionURL' => url('/'), 'order_id' => 101 ]; Notification::send($user, new MyFirstNotification($details)); dd('done'); } }
Route::get('随便写一个你觉得可以的链接', 'HomeController@index'); 比如:Route::get('notify/index', 'HomeController@index');
一会访问链接触发Home控制器的index方法就可以了;
因为User模型中实现了IlluminateNotificationsNotifiable 这个trait,所以:
Notification::send($user, new MyFirstNotification($details));
也可以改成:
$user->notify(new MyFirstNotification($details));
如果需要通过其他方式通知,可以修改via方法:
public function via($notifiable) { return ['mail', 'database','slack']; }
并添加对应的方法 toDatabase
/** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toDatabase($notifiable) { return [ 'order_id' => $this->details['order_id'] ]; }
toSlack
public function toSlack($notifiable) { $message = "Famous Hello World!"; return (new SlackMessage) ->from('Ghost', ':ghost:') ->to('#channel-name') ->content('Fix service request by '.$message); }
或者:
Slack的可以参考 Laravel Notifications – The Ultimate Guide
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->content('Account Registered successfully.'); }
via方法也可以参考 官方文档
public function via($notifiable) { return $notifiable->prefers_sms ? ['nexmo'] : ['mail']; }
而,为什么toMail方法会自动发送到对应的用户的邮箱上,它是如何找到用户的邮箱的 而如果我们要发送的用户的邮箱在数据库的其他字段中的时候,怎么办?
只需要在User类下重写routeNotificationForMail方法即可:
/** * Route notifications for the mail channel. * * @param IlluminateNotificationsNotification $notification * @return array|string */ public function routeNotificationForMail($notification) { // Return email address only... return $this->email_address; // Return name and email address... return [$this->email_address => $this->name]; }
这样通知系统就找email_address字段的值了。
原理如下图:user实现了notifiable trait,下有RoutesNOtifications trait,其中包含一个routeNotificationFor方法;
更多可以查看:
扒一扒 laravel的消息通知(上)
Laravel 论坛系统之消息通知功能
Laravel + 微信小程序 websocket 搭建广播消息系统