本文目录导读:

- 基础方案:通过用户模型定义路由
- 高级方案:基于用户状态动态路由
- 通过Notification类动态路由
- 通过自定义通知服务提供者
- 通过中间件获取动态路由
- 通过Notification Route Builder
- 业务场景示例
- 配置文件设置
- 最佳实践建议
- 生产环境注意事项
在Laravel中实现通知路由按用户动态路由,有几种常见的方案,我来详细说明:
基础方案:通过用户模型定义路由
// app/Models/User.php
class User extends Authenticatable
{
use Notifiable;
// 动态返回通知路由
public function routeNotificationForSms()
{
return $this->phone; // 用户的手机号
}
public function routeNotificationForMail($notification)
{
return $this->email; // 用户的邮箱
}
public function routeNotificationForNexmo($notification)
{
return $this->phone;
}
}
高级方案:基于用户状态动态路由
// app/Models/User.php
class User extends Authenticatable
{
use Notifiable;
public function routeNotificationForMail($notification)
{
// 根据用户偏好动态选择邮件地址
if ($this->preferred_email && $this->preferred_email_enabled) {
return $this->preferred_email;
}
return $this->email;
}
public function routeNotificationForSms($notification)
{
// 根据用户的国家代码动态拼接
return $this->country_code . $this->phone;
}
}
通过Notification类动态路由
// app/Notifications/OrderShipped.php
class OrderShipped extends Notification
{
public function via($notifiable)
{
// 根据用户类型动态选择通知渠道
$channels = ['mail'];
if ($notifiable->sms_notifications_enabled) {
$channels[] = 'sms';
}
if ($notifiable->push_notifications_enabled) {
$channels[] = 'pusher';
}
return $channels;
}
public function toMail($notifiable)
{
// 动态设置邮件接收者
return (new MailMessage)
->to($notifiable->notification_email)
->subject('订单已发货')
->line('您的订单已发货!');
}
}
通过自定义通知服务提供者
// app/Notifications/NotificationServiceProvider.php
class NotificationServiceProvider extends ServiceProvider
{
public function boot()
{
Notification::delivering(function ($notification, $channel, $notifiable) {
// 根据用户动态调整通知路由
if ($notifiable->type == 'premium' && $channel == 'mail') {
$notification->mail_route = $notifiable->premium_email;
}
});
Notification::sent(function ($notification, $channel, $notifiable) {
// 通知发送后的处理
Log::info("Notification sent to user {$notifiable->id} via {$channel}");
});
}
}
通过中间件获取动态路由
// app/Models/User.php
class User extends Authenticatable
{
use Notifiable;
protected $notificationPreferences;
public function getNotificationPreference($channel)
{
// 从缓存或数据库获取用户的动态通知偏好
$this->notificationPreferences = Cache::remember('user_notifications_' . $this->id, 3600, function () {
return $this->notificationSettings()->pluck('value', 'key')->toArray();
});
return $this->notificationPreferences[$channel] ?? null;
}
public function routeNotificationForMail($notification)
{
$preference = $this->getNotificationPreference('mail');
switch ($preference) {
case 'secondary':
return $this->secondary_email;
case 'custom':
return $this->custom_mail_route;
default:
return $this->email;
}
}
}
通过Notification Route Builder
// app/Services/NotificationRouteBuilder.php
class NotificationRouteBuilder
{
public static function buildRoute(User $user, $channel)
{
// 根据用户的配置动态构建路由
switch ($channel) {
case 'mail':
if ($user->getSetting('mail_route') === 'custom') {
return $user->custom_email_address;
}
return $user->email;
case 'sms':
if ($user->getSetting('sms_route')) {
return $user->sms_route;
}
return $user->phone;
case 'pusher':
if ($user->getSetting('pusher_route')) {
return $user->pusher_route;
}
return null;
default:
return null;
}
}
}
业务场景示例
// 在业务逻辑中使用
class OrderService
{
public function sendOrderNotification($order)
{
$user = $order->user;
// 创建通知实例
$notification = new OrderStatusChanged($order);
// 根据用户类型动态发送
if ($user->isVip()) {
// VIP用户使用特殊路由
Notification::route('mail', $user->vip_email)
->route('sms', $user->vip_phone)
->notify($notification);
} else {
// 普通用户使用默认路由
$user->notify($notification);
}
}
}
配置文件设置
// config/notifications.php
return [
'routes' => [
'default' => [
'mail' => 'email',
'sms' => 'phone',
],
'premium' => [
'mail' => 'premium_email',
'sms' => 'premium_phone',
],
'enterprise' => [
'mail' => 'enterprise_email',
'sms' => 'enterprise_phone',
],
],
'channels' => [
'mail' => ['default', 'premium'],
'sms' => ['default'],
],
];
最佳实践建议
// 建议在Notification基类中定义抽象方法
abstract class BaseNotification extends Notification
{
public function getRouteForChannel($channel, $notifiable)
{
// 默认路由
$routeMethods = [
'mail' => 'routeNotificationForMail',
'sms' => 'routeNotificationForSms',
'nexmo' => 'routeNotificationForNexmo',
];
if (method_exists($notifiable, $routeMethods[$channel])) {
return $notifiable->{$routeMethods[$channel]}($this);
}
return null;
}
}
生产环境注意事项
// app/Models/User.php
class User extends Authenticatable
{
use Notifiable;
protected function getNotificationRoutes()
{
// 缓存用户通知路由,减少数据库查询
return Cache::remember("user_notification_routes_{$this->id}", 600, function () {
return [
'mail' => $this->notification_email ?? $this->email,
'sms' => $this->notification_phone ?? $this->phone,
];
});
}
public function routeNotificationForMail($notification)
{
$routes = $this->getNotificationRoutes();
// 如果用户设置了特定通知,使用特定路由
if (isset($notification->custom_routes['mail'])) {
return $notification->custom_routes['mail'];
}
return $routes['mail'];
}
}
这种动态路由机制非常适合:
- 多语言/多地区的用户
- VIP/普通用户不同通知渠道
- 用户偏好设置
- A/B测试不同通知策略
- 特殊业务场景的通知路由
选择哪种方案取决于你的具体需求,建议从简单的开始,逐步演进。