The problem#
While working on my Laravel projects, I noticed a recurring pattern: using closure middleware to skip certain jobs after they’ve been queued. This approach is particularly useful when dealing with delayed jobs that need to be skipped under specific conditions.
Here’s an example of how I was handling this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class MyJob implements ShouldQueue
{
use Queueable;
public function handle(): void
{
// Do something
}
public function middleware(): array
{
return [
function ($job, $next) {
if ($someCondition) {
$next($job);
}
},
];
}
}
|
While this approach works, I thought it would be better to have a more elegant and reusable solution.
The solution: a new Skip
middleware#
To simplify skipping jobs, I created a new middleware class called Skip
. Here’s the implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
class Skip
{
public function __construct(protected bool $skip = false)
{
}
/**
* Apply the middleware if the given condition is truthy.
*
* @param bool|Closure(): bool $condition
*/
public static function when(Closure|bool $condition): self
{
return new self(value($condition));
}
/**
* Apply the middleware unless the given condition is truthy.
*
* @param bool|Closure(): bool $condition
*/
public static function unless(Closure|bool $condition): self
{
return new self(! value($condition));
}
/**
* Handle the job.
*/
public function handle(mixed $job, callable $next): mixed
{
if ($this->skip) {
return false;
}
return $next($job);
}
}
|
Using the Skip
middleware#
Now, the Skip
middleware makes it easier to handle conditional job skipping. Here’s how you can use it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<?php
namespace App\Jobs;
use Illuminate\Queue\Middleware\Skip;
class MyJob implements ShouldQueue
{
use Queueable;
public function handle(): void
{
// Do something
}
public function middleware(): array
{
return [
Skip::when($someCondition),
Skip::unless($someCondition),
Skip::when(function(): bool {
if ($someCondition) {
return true;
}
return false;
}),
];
}
}
|
You use Skip::when()
to skip the job when the condition is truthy and Skip::unless()
to skip the job when the condition is falsy. You can also pass a closure to both methods to define a custom condition.
Submitting the Skip
middleware to Laravel#
Sometimes, small improvements can have a significant impact. Noticing the potential of this middleware, I decided to submit a pull request to Laravel. I’m happy to share that it was accepted by Taylor Otwell.
You can check out the PR here: #52645.
I hope you find this new middleware useful in your projects! 🫶
Keep shipping! 🚢