Parallel requests against the WooCommerce API with the PHP Requests library

Two of my recent articles are about the WooCommerce REST API and the official PHP library from Automattic, which makes the usage of the API with PHP easier. This post describes a way to run multiple requests against a shop at the same time.

The problem when using the API with the official PHP library

If the API is used as I described in my recent posts, then every request pauses the program until the request was finished. If there are only a few requests or requests that depend on each other, that is not that bad, or the wanted behavior.

But if you want to fire API requests that could be bundled, for example, because they should add multiple products, then it would be cool to run those requests parallel. With that, the runtime could be reduced, but that is – as far as I know – not possible with the official PHP lib for the REST API.

The solution: the Requests library

The post »A Guide to Async HTTP Requests for WordPress« by Josh Pollock made me aware of the Requests library by Ryan McCue, that is part of WordPress core for some time now. With its requests_multiple() method, it is possible to run multiple requests at once – exactly what we want.

For example, to make two parallel GET requests, the code could look something like that:

$requests_array = [
		'url'  => '',
		'type' => 'GET',
		'url'  => '',
		'type' => 'GET',

$responses = Requests::request_multiple( $requests_array );

$responses safes the result of both requests.

Usage of the Requests library with the WooCommerce API

A note to the following steps: I did not get it working locally, because request_multiple() currently does not work with self-signed SSL certs (there is an option to deactivate the cert check, but it is not working with the method), and I failed with using OAuth 1 authentication. So the easiest way is to test it on a real server with a valid SSL certificate.

To communicate with the WooCommerce API, we need a URL of the following format (I think it is also possible to provide consumer_key and consumer_secret as HTTP headers, but I did not try that):

The first part until the products/categories endpoint does not change while running requests against one shop; the same goes for both params consumer_key and consumer_secret.

We create a little helper function that returns a API URL for a provided endpoint:

 * Returns URL for accessing the provided WooCommerce REST API endpoint.
 * @param string $endpoint   API endpoint.
 * @param array  $parameters Optional parameters.
 * @return string
function build_api_url( $endpoint, $parameters = [] ) {
	// Add trailing slash to URL.
	$url     = trailingslashit( '' ) . $endpoint;
	$api_url = add_query_arg( \array_merge( $parameters, [
		'consumer_key'    => 'ck_000',
		'consumer_secret' => 'cs_000',
	] ), $url );

	return $api_url;

And now it is possible, for example to retrieve the product categories and attributes, with the following code:

// Make requests to get existing categories and attributes.
$requests = [
		'url'  => build_api_url( 'products/categories' ),
		'type' => 'GET',
		'url'  => build_api_url( 'products/attributes' ),
		'type' => 'GET',

$responses = Requests::request_multiple( $requests );

To create multiple products, the product data could be looped and put into a temporary array, along with the request data. That array could look like that:

$tmp_requests_array[] = [
	'url'     => build_api_url( "products" ),
	'type'    => 'POST',
	'data'    => $prod_data,

Where $prod_data is the array of the product data like described in my article »Creating a WooCommerce product with PHP via the REST API«. After the products were looped and all requests are in the array, we run request_multiple() with the array as the parameter. Maybe you should be a little careful not to send too many requests to the server at the same time.

One thing that currently does not work with requests_multiple() too is providing user and password to access the API of a shop that is saved via .htaccess basic auth.

Related posts

Leave a Comment

Your email address will not be published. Required fields are marked *