Laravel 10邮件添加内存PDF附件时DOMDocument序列化异常求助
解决Laravel 10队列邮件中DOMDocument序列化异常问题
问题根源
你的邮件类实现了ShouldQueue接口,意味着整个邮件对象会被序列化后存入队列。如果邮件类的属性中保留了DOMDocument实例(比如PDF生成库如dompdf内部会持有该实例),而DOMDocument本身不支持PHP序列化,就会触发这个异常。
解决方案
核心思路:不要让不可序列化的对象(如DOMDocument、PDF生成实例)留在邮件类的属性中,只保留可序列化的原始数据(如PDF二进制字符串、订单ID等)。
方案1:在build()方法内生成PDF
把PDF生成逻辑放在邮件的build()方法里,这样生成的PDF实例不会被存入邮件类属性,也就不会参与序列化:
use App\Models\Order; use Illuminate\Mail\Mailable; use Illuminate\Contracts\Queue\ShouldQueue; class InvoiceMail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; // 仅存储必要的可序列化数据,比如订单ID public $orderId; public function __construct(int $orderId) { $this->orderId = $orderId; } public function build() { // 在build方法内生成PDF,用完即销毁实例 $pdf = app('dompdf.wrapper'); $pdf->loadView('invoices.pdf', ['order' => Order::findOrFail($this->orderId)]); $pdfRawData = $pdf->output(); return $this->view('emails.invoice') ->attachData($pdfRawData, 'invoice.pdf', [ 'mime' => 'application/pdf', ]); } }
方案2:构造函数内生成但仅保留PDF原始数据
如果必须在构造函数中处理PDF,确保只存储最终的二进制数据,丢弃包含DOMDocument的实例:
use App\Models\Order; use Illuminate\Mail\Mailable; use Illuminate\Contracts\Queue\ShouldQueue; class InvoiceMail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; public $pdfRawData; public $order; public function __construct(Order $order) { $this->order = $order; // 生成PDF并提取原始数据 $pdf = app('dompdf.wrapper'); $pdf->loadView('invoices.pdf', ['order' => $order]); $this->pdfRawData = $pdf->output(); // 手动销毁PDF实例,避免它被序列化 unset($pdf); } public function build() { return $this->view('emails.invoice') ->attachData($this->pdfRawData, 'invoice.pdf', [ 'mime' => 'application/pdf', ]); } }
额外检查点
- 排查邮件类的所有公共/保护属性,确保没有存储任何包含
DOMDocument的对象(比如第三方PDF库的实例)。 - 如果使用其他PDF生成工具(如TCPDF),同样要确保只保留输出的原始数据,而非工具实例本身。
内容的提问来源于stack exchange,提问作者Gitau Isaac
相关产品推荐
相关产品推荐

