如何在Laravel控制器中调用Mailable类方法?该实现是否符合最佳实践?
现有代码的问题
- 职责划分错误:
Mailable类的核心作用是定义单封邮件的模板、主题、数据等属性,不应该包含发送邮件的业务逻辑,你写的store方法放在ContactMail里不符合Laravel的设计规范。 - 代码错误:
ContactMail中引入的use http\Env\Request;是错误的,Laravel请求类应该用Illuminate\Http\Request。store方法中new contact($contactVar)类名大小写错误,应该是new ContactMail(...),同时你的ContactMail构造函数没有定义参数接收传入的值,直接传参会报错。- 发送逻辑耦合在Mailable中,后续维护、复用都会有问题。
修正方案
第一步:重构ContactMail.php
只保留Mailable本身的逻辑,接收需要传递到模板的数据:
<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class ContactMail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; // 声明为public的属性可以直接在邮件模板中调用 public $name; public $email; public $messageContent; // 构造函数接收从业务层传过来的表单数据 public function __construct($name, $email, $messageContent) { $this->name = $name; $this->email = $email; $this->messageContent = $messageContent; } public function build() { // 可以在这里自定义邮件主题 return $this->subject('新的联系表单提交') ->markdown('emails.contact'); } }
第二步:修改ContactController的submit方法
直接在控制器中调用Mail门面发送邮件,不需要调用Mailable里的store方法:
<?php namespace App\Http\Controllers; use App\Mail\ContactMail; use Illuminate\Http\Request; use Illuminate\Support\Facades\Mail; class ContactController extends Controller { public function submit(Request $request) { $validated = $this->validate($request, [ 'name' => 'required', 'email' => 'required|email', 'message' => 'required' ]); // 发送邮件,收件人可以替换为你的站点管理员邮箱 Mail::to('admin@your-site.com') ->send(new ContactMail( $validated['name'], $validated['email'], $validated['message'] )); // 如果要异步队列发送,把send换成queue即可,因为你已经实现了ShouldQueue接口 // Mail::to('admin@your-site.com')->queue(new ContactMail(...)); return response()->json(null, 200); } }
第三步:调整邮件模板contact.blade.php
直接调用你在ContactMail中声明的public属性即可:
@component('mail::message') # 新的联系表单提交 提交人姓名:{{ $name }} 提交人邮箱:{{ $email }} 提交内容: {{ $messageContent }} @component('mail::button', ['url' => 'mailto:'.$email]) 回复该用户 @endcomponent Thanks,<br> {{ config('app.name') }} @endcomponent
最佳实践说明
- 职责分离:Mailable仅作为邮件的"数据载体",不要在里面写业务逻辑、发送逻辑,所有和业务相关的处理都放在控制器或者单独的服务类中,降低耦合度。
- 数据传递:所有需要在邮件模板中使用的变量,都通过Mailable的构造函数传入,不要在Mailable中直接获取请求、查询数据库,这样Mailable可以在任意业务场景下复用。
- 队列发送:涉及邮件、短信等耗时操作,优先用队列异步发送,避免用户请求等待,只要Mailable实现了ShouldQueue接口,调用queue方法就可以自动加入队列,不需要额外处理。
内容的提问来源于stack exchange,提问作者Artur Müller Romanov
相关产品推荐
相关产品推荐

