Laravel-like job dispatching for WordPress

by Jeffrey van Rossum

Aside from WordPress development, I work a lot with Laravel. And one of the things I love about Laravel, is the Jobs API. In short: a dedicated class for your job that you can dispatch or schedule.

In WordPress, we have the event scheduling mechanism. This too allows you to schedule and 'dispatch' code, through functions like wp_schedule_event and wp_schedule_single_event.

Scheduling tasks in WordPress: The standard approach

A very basic example of a daily scheduled event with WordPress event mechanism looks like this:

function perform_site_health_check() {
    // logic to perform site health check 
}

add_action( 'perform_site_health_check', 'perform_site_health_check' );

Once the action is added, we can schedule it. For daily, we can do:

wp_schedule_event( time(), 'daily', 'perform_site_health_check' );

Or if we want to run it right away:

wp_schedule_single_event(time(), 'perform_site_health_check');

Keep in mind, that for scheduled events, you need to unschedule it (wp_unschedule_event) when your plugin or theme gets deactivated.

Job scheduling and dispatching with WP Job Scheduler

Enter the WP Job Scheduler package. It requires a little bit of setup, but it's worth it. And if you're familiar with Composer - it only takes a couple of seconds.

To install the package, you run:

composer require jeffreyvanrossum/wp-job-scheduler

Then, to set up the scheduler, add this to your plugin or theme code:

WPJobScheduler::instance()
    ->projectRootPath(__DIR__)
    ->scheduler(function() {
        // here we will put the scheduled jobs 
    })
    ->boot();

That's it. Next we will make our job class:

class SiteHealthCheckJob implements Jobable
{
    use IsJob, Schedulable, Dispatchable;

    public function handle()
    {
     	// logic to perform site health check
    }
}

Then you can schedule it:

WPJobScheduler::instance()
    ->projectRootPath(__DIR__)
    ->scheduler(function() {
        SiteHealthCheckJob::schedule('daily'); 
    })
    ->boot();

And if you want to run it right away, you can just:

SiteHealthCheckJob::dispatch();

If you'd like to pass arguments or

Next to the handle method, you can also implement methods like before and after. Those will be called, as you'd expect, before and after the job execution.

You may also add a catch method. This will be called, when the job throws an exception and fails.

public function before(): void
{
	// before the job has been handled
  
    // if for some reason, you now need to cancel the job, run $this->cancel();
}

public function after(): void
{
	// after the job has been handled
}

public function catch(Throwable $e): void
{
  // job failed, maybe do something with the exception
}

You can also pass class constructor arguments, other properties and set a delay in seconds:

SiteHealthCheckJob::dispatch(function($job) {
   $job->wiintuitivethDelay(10);
 
	$job->withProperties(['foo' => 'bar']);
}, ['your_argument' => 'value']);

SiteHealthCheckJob::schedule('daily', function($job) {
   $job->withProperties(['foo' => 'bar']);
}, ['your_argument' => 'value']);

Another nice convenience, is that when you remove a scheduled job from the code, it will automatically be unscheduled. You don't have to manually run code to unschedule your job - like you would have to with the default WordPress event mechanism.

Reliable job handling with the action scheduler

Under the hood the package uses the action scheduler package from the folks over at WooCommerce. In my experience, using this package makes dispatching jobs a more reliable.

In closing

I think it's nice, through package like this, to bring some of the intuitive syntax from Laravel to WordPress. Though, admittedly, it's only inspired by it and certainly not exactly the same or as advanced. But still, a nice improvement in my opinion.

The package (here at GitHub) is still in early development, but feel free to test/use it and let me know what you think.

Comments

Talk about this article on X.
Did you like this post?

If you sign up for my newsletter, I can keep you up to date on more posts like this when they are published.