How and why wrapping Laravel HTTP API request inside Laravel job?
Janez Cergolj • February 3, 2023
Hey there! Today we're talking about how to wrap Laravel Http API client requests in Laravel Jobs for improved efficiency. But first, let's go over the requirements - not all API requests are suitable for this method. Only use it for requests where an instant response isn't necessary.
Now, for the benefits
Code
Here's an example of how you can use Laravel Jobs to get newly created candidates from one service and update their gender using another API.
A command
First, we'll create a TrackNewlyCreatedCandidatesCommand that dispatches a job to fetch all newly created candidate HTTP client requests.
<?php
namespace App\Console\Commands;
use App\Jobs\TrackNewlyCreatedCandidatesJob;
use Illuminate\Console\Command;
class TrackNewlyCreatedCandidatesCommand extends Command
{
protected $signature = 'track-newly-created-candidates';
protected $description = 'get newly created candidates';
public function handle()
{
TrackNewlyCreatedCandidatesJob::dispatch();
return Command::SUCCESS;
}
}
TrackNewlyCreatedCandidatesJob job
Next, we have the TrackNewlyCreatedCandidatesJob that makes the first API request to fetch all newly created candidates. If the request is successful, it dispatches an independent UpdateCandidateGenderJob for each candidate.
<?php
namespace App\Jobs;
use App\Jobs\Bullhorn\UpdateCandidateGenderJob;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class TrackNewlyCreatedCandidatesJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle()
{
$response = Http::get(...);
collect($response->json())->each(function ($candidate) {
UpdateCandidateGenderJob::dispatch($candidate);
});
}
}
UpdateCandidateGenderJob job
Why dispatch for each candidate its UpdateCandidateGenderJob job?
Separation of Concerns
Jobs are ideal for adhering to the principle of single responsibility, where each class should have only one specific task. Smaller classes are easier to read, understand, modify, and test.
Handle Failed Jobs
In the event that one of the UpdateCandidateGenderJob jobs fails, the other jobs will still run. This code behaves like a batch rather than a chain of jobs. Each job runs independently, without relying on the outcome of others.
<?php
namespace App\Jobs\Bullhorn;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class UpdateCandidateGenderJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* @param array $candidate
* @return void
*/
public function __construct(public array $candidate)
{
}
public function handle()
{
$response = Http::get();
// ...
}
}
That's it! This is why HTTP API client requests should be wrapped in Laravel Jobs. If you have any questions or want to know more about testing this approach or automatically retrying failed jobs, hit me up on Twitter.