LoginSignup
0
1

Serialization of 'Closure' is not allowedというエラーを理解する

Last updated at Posted at 2023-09-20

エラーが起きた経緯

Laravelで以下のようにユーザ登録をしたときにユーザにメール通知を送るようにしていました。

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        $user->registered($request);

registered関数はNotificationクラスを使って通知を送るものです。

今回、通知を非同期処理にしようと思い、Notificationクラスにimplements ShouldQueueを追記しました。

すると、ジョブは正常にキューに追加できずに
Serialization of 'Closure' is not allowed
というエラーが発生しました。

エラー文の解読

  1. Serializationとは:
    シリアライズとは、オブジェクトを文字列やバイナリの形式に変換するプロセスのことを指します。Laravelのキューシステムでは、ジョブをキューに追加する際に、ジョブに関連するデータがシリアライズされ、後でデシリアライズされて処理されるそうです。

  2. Closureのシリアライズ:
    エラーメッセージは、Closure をシリアライズすることはできないと指摘しています。
    一般的に、クロージャ(無名関数)やリソースへの参照(例えばデータベースの接続やファイルハンドルなど)はシリアライズできず、Request オブジェクトにはそれらが含まれている可能性があります。

$requestの中身

実際、ddでリクエストの中身を見てみると、Closureが確認できましたスクリーンショット 2023-09-21 0.38.10.png

解決策: $request->all() を使用する

冒頭のコードのregistered関数に与える引数を変更しました

        $user->registered($request->all());

$request->all()は、リクエストの入力データを連想配列として取得できます。この連想配列はシリアライズ可能なので、ジョブのクラスに渡して使用することができます。

要するに、ジョブやイベントをキューに追加する際には、シリアライズ可能なデータのみを渡す必要があるみたいです。ここでも、リクエストオブジェクトそのものを渡すのではなく、必要なデータだけを取り出してジョブに渡す必要があります。

補足

メールのフォーマットに渡すデータをオブジェクトではなく連想配列にしたので、その取り出し方の記述も以下のように変えた


//変更前
{{ $user->name }}さんこんにちは<br>

//変更後
{{ $user['name'] }}さんこんにちは<br>
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1