Dispatch() of Laravel job can have certain conditions like dispatchIf, dispatchUnless, etc. Lets learn all dispatch options provided by Laravel.
Table of Content
Dispatch
You can directly dispatch your job using dispatch() method.
DispatchIf and DispatchUnless
You can use these two dispatch methods to run your job or based on the condition provided. Using both is like using true and !true condition inside the if statement. If you pass a condition that return true for both dispatchIf and dispatchUnless it behave like true and !true nature.
//Dispatch only if the condition is true.
ProcessImage::dispatchIf(condition, ....arguments);
ProcessImage::dispatchIf(true, $user); //Execute
ProcessImage::dispatchIf(false, $user); //Does not execute
//Dispatch only if the condition is false
ProcessImage::dispatchUnless(condition, ....arguments);
ProcessImage::dispatchUnless(true, $user); //Does not execute
ProcessImage::dispatchUnless(false, $user); //Execute
Delay job dispatch
Here you can delay adding the Laravel job to the queue in order to delay the dispatch process. Use delay() method on the dispatch() method.
//Add this job to queue after 5 minutes delay
ProcessImage::dispatch()->delay(now()->addMinutes(5));
Without Delay method
You can add a delay variable to job classes to delay job being added to queue for processing. If there is a need to execute that job without the default delay you can use withoutDelay() method on dispatch() method.
Laravel Job with a default delay
create a sample job class called ProcessImage using below artisan command.
php artisan make:job ProcessImage
Modify ProcessImage job class.
- Here we are using $delay variable in Queueable trait.
- Define $delay variable to override default variable in the Queueable trait.
- Add your delay value inside the constructor.
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;
class ProcessImage implements ShouldQueue
{
use Queueable;
public $delay;
/**
* Create a new job instance.
*/
public function __construct()
{
$this->delay = 10;
}
/**
* Execute the job.
*/
public function handle()
{
Log::info("Done Processing Image Processing Job");
}
}
Now dispatch above created job class. Open web.php.
<?php
use App\Jobs\ProcessImage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
Log::info("Received a get request on root route");
ProcessImage::dispatch();
});
Run above application
php artisan serve
Run a queue worker
php artisan queue:work
Check logs
- There is a 10 seconds delay (more than 10 seconds since job was added to queue after 10 seconds. Actual processing time will be higher than 10 seconds) before executing the job.
[2024-12-24 00:58:44] local.INFO: Received a get request on root route
# 10 seconds delay before adding job to the queue
[2024-12-24 00:58:55] local.INFO: Done Processing Image Processing Job
Overriding default delay of a Laravel job class
We can use withoutDelay() method on the dispatch() method to execute laravel job class overriding any defined delays in the job class.
<?php
use App\Jobs\ProcessImage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
Log::info("Received a get request on root route");
ProcessImage::dispatch()->withoutDelay();
});
Logs:
Job class immediately added to the queue for processing.
[2024-12-24 01:11:10] local.INFO: Received a get request on root route
[2024-12-24 01:11:11] local.INFO: Done Processing Image Processing Job
Dispatch Sync method
Imagine you have a Laravel job that uses queueable interface. You want one instance of that job class to execute on the same http request immediately without moving it to the queue for later processing. You can use dispatchSync method instead of dispatch method.
Example using DispatchSync method
Create a sample Laravel job using below artisan command.
php artisan make:job ProcessImage
Add below code to ProcessImage job class.
- Accept string argument when dispatching the job. Constructor $data variable.
- Add 10 second sleep to simulate time consuming task.
- Log before and after the sleep to track when the job processing start and end.
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;
class ProcessImage implements ShouldQueue
{
use Queueable;
/**
* Create a new job instance.
*/
public function __construct(public string $data)
{ }
/**
* Execute the job.
*/
public function handle()
{
Log::info("Processing... $this->data");
sleep(10);
Log::info("Done... $this->data");
}
}
Now use disptach and dispatchSync to process this job. Here we are using web.php file.
- Run three instances of the same job.
- Use dispatch() on the first 2 instances of the same job to create a queue.
- Use dispatchSync() on last job instance to see what happen.
<?php
use App\Jobs\ProcessImage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
Log::info("Received a get request on root route");
ProcessImage::dispatch('::Dispatch method');
ProcessImage::dispatch('::Dispatch method');
ProcessImage::dispatchSync('::Dispatch Sync');
return "success";
});
Now check Laravel logs. Even though DispatchSync job was called at the end, it start processing and completed the job before all others.
[2024-12-24 10:43:41] local.INFO: Received a get request on root route
[2024-12-24 10:43:41] local.INFO: Processing... ::Dispatch Sync
[2024-12-24 10:43:44] local.INFO: Processing... ::Dispatch method
[2024-12-24 10:43:51] local.INFO: Done... ::Dispatch Sync
[2024-12-24 10:43:54] local.INFO: Done... ::Dispatch method
[2024-12-24 10:43:54] local.INFO: Processing... ::Dispatch method
[2024-12-24 10:44:04] local.INFO: Done... ::Dispatch method