如何将数据库数据传递到Mailable?DB::select应放在控制器还是Mailable?
向Mailable传递数据的实现方式
你可以通过Mailable的构造函数接收外部传入的数据,只要将数据赋值给Mailable的公共属性,该属性会自动暴露给对应的邮件模板,不需要额外调用with方法传递。
DB查询的放置位置建议
优先把DB::select查询逻辑放在Controller层(更规范的实现是抽离到独立的Service/Repository层),不要放在Mailable中,原因如下:
- 符合单一职责原则:Mailable的定位是负责邮件格式、内容渲染的封装,不应该承担数据查询的业务逻辑
- 复用性更强:相同的查询逻辑如果其他业务需要调用,可以直接复用,不需要重复编写
- 队列兼容性更好:如果你的Mailable开启了异步队列,放在构造函数中的查询会在任务推入队列时执行,如果队列有延迟发送的配置,查询到的数据可能和实际发送时的最新数据不一致;同时查询逻辑放在Controller中如果出错会直接在请求阶段抛出,更方便排查问题
现有代码修正
你现有代码存在两个明显问题:
- Controller中引用的是
ContactMail类,但你的Mailable类名是TestMail,属于笔误会报错 TestMail的build方法中调用with('data', $data)的$data未声明,需要加$this->才能读取类的属性
修正后TestMailController.php代码
<?php namespace App\Http\Controllers; use App\Mail\TestMail; use Illuminate\Http\Request; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\DB; class TestMailController extends Controller { public function test() { // 数据查询放在Controller层 $data = DB::select('select * from db_name'); // 把查询结果传入Mailable构造 return new TestMail($data); } }
修正后TestMail.php代码
<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class TestMail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; // 公共属性,会自动传递给邮件模板 public $data; // 接收外部传入的数据 public function __construct($data) { $this->data = $data; } public function build() { // 公共属性已经自动传给模板,不需要再写with,如果你需要自定义变量名也可以加with return $this->markdown('emails.testmail'); } }
内容的提问来源于stack exchange,提问作者Artur Müller Romanov
相关产品推荐
相关产品推荐

