You may run into this exception in Laravel as soon as you attempt to queue a Mailable class. Let me quickly explain why this may happen and how to avoid it.
Background
Sending e-mails is an easy to do task, yet it may have a huge impact on app's performance and therefore user's experience. Typically you would try to immediately send your Mailable
like:
Mail::to(config('mail.to.address'))->send(new ContactForm($request));
This may cause a significant delay as we send it synchroniously. User simply has to wait for the server to respond after message is being sent.
Thanks to Laravel's unified queue API, you can swap send()
method with queue()
to dispatch it on a queue and send asynchronously (once the associated job is being processed).
Mail::to(config('mail.to.address'))->queue(new ContactForm($request));
The Problem
The Mailable
class in Laravel uses SerializesModels
trait. Before a job can be dispatched on a queue, it has to be serialized. If your class has a constructor where you inject a dependency, such as Request:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Http\Request;
use Illuminate\Queue\SerializesModels;
class ContactForm extends Mailable
{
use Queueable;
use SerializesModels;
public function __construct(
public Request $request,
) {}
(…)
an exception will be thrown by the framework:
[2024-11-14 18:24:02] local.ERROR: Exception: Serialization of 'PDO' is not allowed in /var/www/vendor/laravel/framework/src/Illuminate/Queue/Queue.php:160
Stack trace:
#0 /var/www/vendor/laravel/framework/src/Illuminate/Queue/Queue.php(160): serialize(Object(Illuminate\Mail\SendQueuedMailable))
Solution
The solution is to replace injected dependencies, with objects that can be correctly serialized. In my case, instead of relying on the Request
object, I have replaced that with a dedicated DTO class, containing all the attributes I was previously obtaining from the Request
. One complicated dependency less.