LoginSignup
2024_Hello_World
@2024_Hello_World

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

[Laravel]ディスパッチできない

Q&AClosed

解決したいこと

Laravelでジョブを作成したが、ディスパッチができません。
コードに間違いがあれば教えてください。

ディスパッチを行いnameに[+MYJOB]というテキストを追加し、すでに[+MYJOB]が追加されている場合は、それを削除します。

発生している問題・エラー

nameに[+MYJOB]が追加されない。

スクリーンショット 2024-04-04 135638.png
↓このように表示させたいです。

スクリーンショット 2024-04-04 135709.png

該当するソースコード

web.php
<?php

use App\Http\Controllers\HelloController;
use Illuminate\Support\Facades\Route;

Route::get('hello',[HelloController::class,'index']);
Route::get('/hello/{person}', [HelloController::class, 'index']);
HelloController.php
<?php

namespace App\Http\Controllers;

use App\Jobs\MyJob;
use App\Models\Person;

class HelloController extends Controller
{
    public function index(Person $person = null)
    {
        if ($person != null)
        {
            MyJob::dispatch($person);
        }
        $msg    = 'show people record.';
        $result = Person::get();
        $data = [
            'input' => '',
            'msg'   => $msg,
            'data'  => $result,
        ];
        return view('hello.index', $data);
    }
}
MyJob.php
<?php

namespace App\Jobs;

use App\Models\Person;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class MyJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     */

    protected $person;

    public function __construct(Person $person)
    {
        $this->person = $person;
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        $sufix = '[+MYJOB]';
        if (strpos($this->person->name, $sufix))
        {
            $this->person->name = str_replace( $sufix, '', $this->person->name);
        }
        else
        {
            $this->person->name .= $sufix;
        }
        $this->person->save();
    }
}

MyJobProvider.php
<?php

namespace App\Providers;

use App\Jobs\MyJob;
use Illuminate\Support\ServiceProvider;

class MyJobProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        $this->app->bindMethod(MyJob::class.'handle', function($job, $app)
        {
            return $job->handle();
        });
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        //
    }
}

Person.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Person extends Model
{
    public function getAllDataAttribute()
    {
        return $this->name . '(' . $this->age . ')' . '[' . $this->mail . ']';
    }
}
index.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>Index</title>
</head>
<body>
    <h1>Hello/Index</h1>
    <p>{{$msg}}</p>
    <div>
        <form action="hello" method="post">
            @csrf
            <input type="text" id="find" name="find" value="{{$input}}">
            <input type="submit">
        </form>
    </div>
    <hr>
    <table border = "1">
        @foreach ($data as $item)
            <tr>
                <th>{{$item->id}}</th>
                <td>{{$item->all_data}}</td>
            </tr>
        @endforeach
    </table>
    <hr>
</body>
</html>
0

1Answer

  • Laravelの話をする時は必ずバージョンを書く。
  • Laravelの使い方を覚える方法は「公式ドキュメントを読む」以外には絶対に存在しない。すでに「公式ドキュメント以外は読むな」が常識。英語のドキュメントをChromeで翻訳して読めばいい。

まずキューとは何かを理解してないのでは。
https://laravel.com/docs/11.x/queues

コントローラーの流れとは別でバックグラウンドで処理するのが本来のキュージョブ。
MyJob::dispatch()自体は正しく動いている。
「MyJobは後でバックグラウンドで動かして」とお願いするところまで。キューに入れてるだけでMyJobの中身は動いてない。

なぜ本と違うのかというとLaravel11で変わったから。
Laravel11ではQUEUE_CONNECTION=database
https://github.com/laravel/laravel/blob/708fdb1a36fd4567a2b7fd7557436536005fe4d2/.env.example#L37
Laravel10までは長らくQUEUE_CONNECTION=sync
https://github.com/laravel/laravel/blob/7effeb99ec1568f006ed95e60d3e7dfeed1b8160/.env.example#L21

syncドライバーではMyJob::dispatch()はその場で即実行される。
MyJobでのPersonの変更が反映されるのでその後のPerson::get()で更新後のデータが得られる。

databaseドライバーではキューに入れるだけでMyJobは実行されない。
Personが変更されてないのでPerson::get()も変わらない。

本と同じ結果にしたいならMyJob::dispatchSync($person)にすればいいだけ。強制的にsyncで実行。
間違ったジョブの使い方だけど。

元凶は「デフォルトがsyncドライバーだから偶然上手く動いてただけのことを普通の使い方のように書いてるその本」

ついでにbindMethodは意味不明。正しいのはMyJob::class.'@handle'だろうけどそんなところを指摘する以前の話でbindMethodなんて使わない。このコードは不要だろう。

$this->app->bindMethod(MyJob::class.'handle', function($job, $app)
        {
            return $job->handle();
        });

何もかも間違ってるその本はやばすぎる…。明らかにLaravelを知らない初心者が適当に触ってたまたま上手く行ったことを書いてるだけ。

1

Comments

  1. ご回答いただきありがとうございます!
    Laravelは最近始めたので勉強になります
    キューは非同期処理の時につかうこと学びました
    ご指摘の通り本だけでは間違った情報もあるようなので、ドキュメントも活用していきます!

Your answer might help someone💌