Laravel本身不内置短信通道,必须自配服务商或引入第三方包;否则Notification::send()会静默失败或抛出“Driver [sms] not supported”错误。需在AppServiceProvider中注册SmsChannel,via()返回['sms']才生效;toSms()必须返回含to、template、data的数组,字段名与服务商要求严格匹配,否则静默丢弃。

直接发不了,Laravel 本身不内置短信通道,必须自己配服务商 + 实现 Channel 或引入第三方包;否则 Notification::send() 调用时会静默失败或抛出 InvalidArgumentException: Driver [sms] not supported。
via() 里写了 'sms' 却没效果?检查 Channel 是否注册
Laravel 不认识 sms 这个渠道名,除非你手动注册。官方只内置 mail、database、broadcast 等,sms 是纯自定义的。
- 在
App\Providers\AppServiceProvider的boot()方法里加:Notification::extend('sms', function ($app) { return new SmsChannel(); }); -
SmsChannel类需实现send()方法,内部调用阿里云 SDK、Twilio Client 或 cURL 请求 - 若用现成包(如
laravel-notification-channels/twilio),注册步骤由服务提供者自动完成,但必须确认config/app.php中已加载其ServiceProvider - 漏掉注册 →
via()返回['sms']会被忽略,toSms()根本不会执行
toSms() 返回空、null 或字段名写错,短信就丢得无声无息
toSms($notifiable) 是 Laravel 唯一找短信参数的地方,它不校验、不报错、不重试 —— 返回啥就传啥给 Channel,返回空字符串就等于发了个空请求。
- 常见错误:
return $this->phone;,但数据库字段其实是mobile,结果返回null - 微信用户存
open_id在关联表?不能直接写$this->wechatUser->open_id,得加空值判断:return $this->wechatUser?->open_id ?? ''; - 阿里云短信要求
toSms()返回数组包含to(手机号)、template(模板 code)、data(变量),缺任意一项,SDK 可能静默失败 - 模板
code必须和阿里云控制台审核通过的完全一致:大小写、下划线、中划线都不能错,SMS_12345678和sms_12345678是两个不同模板
队列卡住、日志没报错?多半是驱动配置或队列连接没对上
通知走同步时页面会卡死,切队列后又没动静,问题往往不在通知逻辑,而在基础设施层。
- 用
database队列:必须先跑php artisan queue:table && php artisan migrate,否则任务写不进jobs表 - 用
redis队列:Docker 环境下REDIS_HOST别写localhost,得填容器名(如redis) - 服务商凭证填错位置:阿里云 key 得塞进
config/services.php的aliyun_sms数组里,不是alisms或aliyun—— 名字不对,Channel 初始化就拿不到配置 - 本地开发用微信测试号?别缓存配置:
php artisan config:cache会让env('WECHAT_ENV')固化为production,导致读错 app_id
短信+微信双通道怎么避免重复发?via() 不能硬写数组
默认 via() 返回 ['sms', 'wechat'] 是并行触发,两个都发;但业务常要「微信优先,失败再补短信」,这得靠逻辑降级,不是靠队列重试。
- 别在
via()里写死数组,改用条件判断:return $notifiable->prefersWechat() ? ['wechat'] : ['sms']; - 更稳妥的做法:统一走
['wechat', 'sms'],但在toWechat()和toSms()内部各自捕获异常,失败时记录日志或触发 fallback 事件 - 注意:Laravel 不会自动把一个渠道失败的结果透传给另一个渠道,降级必须手动编码,没有「自动 fallback」机制
最易被忽略的一点:所有短信渠道的 toXxx() 方法返回值,必须严格匹配对应 Channel 所期望的结构 —— Twilio 要 to/from/body,阿里云要 to/template/data,错一个 key 就发不出去,且几乎不报错。


















