建立一個系統來發送通知給用戶,以下內容是經多次改版出來,只為自己筆記為主,順便分享,當然未來如果做了簡化工作,我會再來更新
假設系統名為 Notic Model 來保存所有記錄
我故意不使用Notificationt這個字, 因為這個名稱Laravel內部已使用,甚至我整個流程中也會用到Notification來協助我們寄出通知,因為我們的SystemNotic是 extends Notification
Model Notic.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Notic extends Model
{
use SoftDeletes;
public $incrementing = false; // 禁用自增
protected $keyType = 'string'; // 設置主鍵類型為字符串
protected $table = 'notifications'; // 使用 Laravel 默認表名
protected $fillable = [
'id', // UUID
'type', // 通知類型
'title', // 通知標題
'content', // 通知內容
'notifiable_type', // 默認會是 'App\Models\User'
'notifiable_id', // 用戶 ID
'data', // JSON 數據,可以包含我們的自定義字段
'read_at', // 已讀時間
'created_at',
'updated_at'
];
protected $casts = [
'data' => 'array',
'read_at' => 'datetime',
'created_at' => 'datetime',
'updated_at' => 'datetime'
];
// 我們可以通過 data 字段存儲額外信息
public function getTitleAttribute()
{
return $this->data['title'] ?? '';
}
public function getContentAttribute()
{
return $this->data['message'] ?? '';
}
public function getTypeAttribute()
{
return $this->data['type'] ?? 'info';
}
public function user()
{
return $this->belongsTo(User::class, 'notifiable_id');
}
}
建立一個通知 app/Notifications/SystemNotic.php
這是extends Notification
的!
<?php
namespace App\Notifications;
use Illuminate\Notifications\Notification;
class SystemNotic extends Notification
{
protected $title;
protected $message;
protected $type;
protected $data;
public function __construct($title, $message, $type = 'info', $data = [])
{
$this->title = $title;
$this->message = $message;
$this->type = $type;
$this->data = $data;
}
public function via($notifiable)
{
return ['database'];
}
public function toDatabase($notifiable)
{
return [
'title' => $this->title,
'message' => $this->message,
'type' => $this->type,
'data' => array_merge($this->data, [
'title' => $this->title,
'message' => $this->message,
'type' => $this->type
])
];
}
}
建立一個 Service app/Services/NoticService.php
<?php
namespace App\Services;
use App\Models\User;
use App\Notifications\SystemNotic;
use Illuminate\Support\Facades\Notification;
class NoticService
{
/**
* 發送通知給指定用戶
*/
public function sendToUser($userId, $title, $message, $type = 'info', $data = [])
{
$user = User::find($userId);
if ($user) {
$user->notify(new SystemNotic($title, $message, $type, $data));
}
}
/**
* 發送通知給多個用戶
*/
public function sendToUsers($userIds, $title, $message, $type = 'info', $data = [])
{
$users = User::whereIn('id', $userIds)->get();
Notification::send($users, new SystemNotic($title, $message, $type, $data));
}
/**
* 發送通知給所有用戶
*/
public function sendToAll($title, $message, $type = 'info', $data = [])
{
$users = User::all();
Notification::send($users, new SystemNotic($title, $message, $type, $data));
}
}
建一個 Traits app/Traits/HasNotics.php
<?php
namespace App\Traits;
use App\Services\NoticService;
trait HasNotics
{
public function notic()
{
return app(NoticService::class);
}
}
使用方法
發送通知
// 方法 1: 使用 NoticService
$noticService->sendToUser(
auth()->id(),
'通知標題',
'通知內容',
'info', // 通知類型: info, success, warning, danger
['action' => 'view_task'] // 額外數據
);
// 發送給單個用戶
$noticService->sendToUser(1, '任務列表已更新', '您有新的任務');
// 發送給多個用戶
$noticService->sendToUsers([1, 2, 3], '任務列表已更新', '有新的任務');
// 方法 2: 使用 HasNotics Trait
$model->notic()->sendToUser(
auth()->id(),
'通知標題',
'通知內容'
);
推薦使用 Trait 方法2,方便在模型中使用
Demo:當修改客戶資料時,產生一則通知
設定 Model : app/Models/Customer.php
use App\Traits\HasNotics; //上方加入
class Customer extends Model {
use HasFactory, HasNotics; //加入HasNotics,保留你原有的
...
}
修改 CustomerController.php
public function update($id, Request $request) {
$customer = Customer::find($id);
$customer->fill($request->all());
$customer->save();
// 發送系統內部通知
$customer->notic()->sendToUser(
Auth::id(),
'客戶更新通知',
'客戶資料已更新'
);
}
如果用方法1,需要在每次執行的Controller
引入NoticService
, 但我認為這些通知功能應該是只需要設定一次永久使用,修改的機會不大,所以我認為方法2 直接整合在 Model 會更好,因為在Controller
完全不用做任何引入和設定。
這次亦令我了解到Trait的好處,相信日後會更多機會用到。