API Booster
Description
Seamlessly use the API
The Akeneo PIM web API is well documented, robust and more importantly stable which makes it a great way to connect your PIM. It has one drawback nonetheless : importing products requires the same complex and costly boilerplate code on every project as the API is very strict. API booster fixes this problem.
Imagine you want to import a product via the API. It has two attributes : a_boolean
and a_date
. Your input data is probably heterogeneous as it comes from various sources. As the Akeneo API is really strict, you need to format that data correctly. You need to know the attribute a_boolean
is a boolean, so you call the GET AN ATTRIBUTE endpoint. Same for the a_date
attributes. If you have a lot of attributes data per product to handle, you can’t afford an API call for each attribute. You’re smart and use the GET LIST OF ATTRIBUTES endpoint instead. Great! But now you need a lot more API calls to know if the foo
attribute option really exists, if this bar
reference entity record is valid or if the baz
asset is still present. You must perform those API calls and many others, otherwise your whole product wouldn’t be updated if only one of these elements was invalid. The bad thing is you have (hundreds of) thousands of products data to import. Calling constantly back and forth the Akeneo API will be incredibly slow. You’re smart and you understand you’ll need a caching system. Good news, API booster is here for you!
API Booster is a PHP caching library dedicated to handle Akeneo PIM API calls. It’s compatible with every cache provider you can think about and super simple to use. For instance, $attribute = $apiBooster->getAttribute(‘a_boolean’);
will return the a_boolean
attribute from the cache or call the API and store it in the cache before returning it. It goes the same for every catalog structure resource. API Booster also provides a convenient method to format input data via $apiBooster->formatProduct($data)
($apiBooster->formatProductModel($data)
). You can learn more about it in the Documentation.
API Booster ships with several demos :
- one to show how API Booster can be integrated inside a Symfony project
- one to show how API Booster can be integrated inside a non Symfony project or inside a PHP project that does not use any framework
- one to show how using API Booster can drastically improve performances. On this very simple example, performances are improved by ~9. Of course, the bigger the catalog and/or the products (or product models) are, the bigger this ratio would be.
Features
- A simple, powerful and versatile cache solution for all resources of the catalog structure that need to be defined when creating or updating a product or a product model. That includes categories, attributes, attribute options, attribute groups, association types, locales, channels, currencies, measure families, measurement families, reference entity records and assets.
- Drastically improve performances compared to naive API calls.
- An opinionated way to format input data into API format.
- 100% Akeneo API compatible. It relies on the official Akeneo API client. No change is made to API responses and errors.
- A convenient way to debug and log when you call the API or when you directly use the cache.
- Examples about how to use the library
FAQ
Which kind of caches are supported?
Every caching library that supports PSR6 or Symfony’s cache contracts. That means you can use memcached, Redis, APCu, Couchbase, Doctrine, the memory, the filesystem and many others caching solutions. You can also combine several caching systems to create a cache chain if you need to.
If your project is Symfony based, you just have to configure your caches in your configuration file. All those caches will work out of the box. If you don’t have a Symfony project, no worries, API booster is simple and straightforward to configure.
Which API resources are supported?
All resources of the catalog structure that need to be defined when creating or updating a product or a product model :
- Attribute
- Attribute option
- Category
- Attribute group
- Association type
- Locale
- Channel
- Currency
- Reference entity record
- Asset
- Measure family
- Measurement family
Depending on the version of Akeneo you use, some endpoints may be unavailable.
Which Akeneo editions are supported?
All editions. Community, Enterprise, Flexibility and Serenity.
Which Akeneo versions are supported?
All versions ⩾ Akeneo PIM 3.0. That includes v3.0, v3.1, v3.2, v4.0 and SaaS Serenity.
Is there a cache for products and product models?
No. Since in most cases products and product models data need to be fresh. Contact me in case of need.
Is it compatible with every PHP application?
Yes. This extension is standard PHP code that can be integrated in every existing application. As it relies on the official Akeneo API client, it requires PHP ⩾ 7.1.
Is it compatible with every PHP framework?
Yes. Even if at the moment, only Symfony is plug and play. Contact me in case of need.
What if I don’t use PHP on my project? What about an HTTP cache?
It’s easy to build an HTTP cache middleware on top of this extension. Contact me in case of need.
Which cache solution to use?
It's up to you! The two most known cache solutions are probably memcached and Redis. They both work well for our use case and both have their pros and cons. If you want to know more about different cache solutions, you can take a look to this article.
What about memory consumption?
Depending on the size of your catalog, the memory footprint of your cache can grow. To know about your needs and what could happen in production, the best is probably to try beforehand to cache everything you'll need on a staging environment.
What if I have very special needs for my very special project?
You can contact me :)
Whose is behind API booster?
Julien Janvier is an Akeneo expert freelancer who can intervene on any type of project, whether it is custom developments, connector integrations (by files or API), installations or migrations. He has recently retired from Akeneo where he worked for 6 years as a developer, lead developer and architect. He also holds Akeneo's technical and functional certifications.
Contact
You can drop me an email at “j dot janvier at gmail dot com” or send me a message on Linkedin.
Release notes
1.0.1 - Minor release
- enhance public API
- enhance documentation
1.0.0 - First release
- A simple, powerful and versatile cache solution for all resources of the catalog structure that need to be defined when creating or updating a product or a product model. That includes categories, attributes, attribute options, attribute groups, association types, locales, channels, currencies, measure families, measurement families, reference entity records and assets.
- Drastically improve performances compared to naive API calls.
- An opinionated way to format input data into API format.
- 100% Akeneo API compatible. It relies on the official Akeneo API client. No change is made to API responses and errors.
- A convenient way to debug and log when you call the API or when you directly use the cache.
- Examples about how to use the library
Documentation
Features' details
Retrieving a resource from the cache
For instance, if we want to retrieve the attribute which code is my_attribute
:
$attribute = $apiBooster->getAttribute(‘my_attribute’);
The method will return the response that is normally returned by the API. No changes are made. As the official Akeneo PHP client is used internally, that means it can either return an array containing all data of this attribute in case of success, or throw an Akeneo\Pim\Exception\HttpException in case of error. If the response is a success, it will be stored in the cache to prevent the API to be called next time.
The other methods getAttributeOption
, getCategory
, getAttributeGroup
, getAssociationType
, getLocale
, getChannel
, getCurrency
, getReferenceEntityRecord
, getAsset
, getMeasureFamily
and getMeasurementFamily
work the same.
Knowing the type of an attribute
Internally, the cache will be called, which means you can use this method without suffering any penalty hit.
$attributeType = $apiBooster->getAttributeType(‘my_attribute’);
Format input data into API format
The methods formatProduct
(and formatProductModel
) allows to automatically format product (and product model) values. All you have to do is to respect the global format expected by Akeneo PIM API.
Please note that those methods do not send the products data to Akeneo. They are just here to format the data.
Format booleans
The strings 1
, true
and yes
are converted to the boolean true
for boolean attributes. This also works for the German ja
, the Spanish sí
, the French oui
, the Italian si
, the portuguese sim
, the Swedish ja
and the Russian да
/ da
. For instance :
$formatted = $apiBooster->formatProduct([ 'values' => [ 'a_boolean' => [ [ 'locale' => null, 'scope' => null, 'data' => 'oui'], ] ] ]); // $formatted = [ // 'values' => [ // 'a_boolean' => [ // [ 'locale' => null, 'scope' => null, 'data' => true], // ] // ] // ];
The strings 0
, false
and no
are converted to the boolean false
for boolean attributes. This also works for the German nein
, the Spanish no
, the French non
, the Italian no
, the Portuguese não
, the Swedish nej
and the Russian нет
/ nyet
. For instance :
$formatted = $apiBooster->formatProduct([ 'values' => [ 'a_boolean' => [ [ 'locale' => null, 'scope' => null, 'data' => '0'], ] ] ]); // $formatted = [ // 'values' => [ // 'a_boolean' => [ // [ 'locale' => null, 'scope' => null, 'data' => false], // ] // ] // ];
Format collections
The strings containing a given separator are split and converted to arrays for asset collections, multi selects and reference entity collections. For instance :
$formatted = $apiBooster->formatProduct([ 'values' => [ 'a_multi_select' => [ ['locale' => null, 'scope' => null, 'data' => 'foo,bar'], ] ] ]); // $formatted = [ // 'values' => [ // 'a_multi_select' => [ // ['locale' => null, 'scope' => null, 'data' => ['foo', 'bar']], // ] // ] // ];
The default separator for collections is ,
. If you need a different separator, you can provide it as a second argument of the methods formatProduct
and formatProductModel
. For instance :
$formatted = $apiBooster->formatProduct([ 'values' => [ 'a_multi_select' => [ ['locale' => null, 'scope' => null, 'data' => 'foo|bar'], ] ] ], '|');
Format dates
The \DateTime
and \DateTimeImmutable
objects are converted to ISO-8601 for date attributes. For instance :
$formatted = $apiBooster->formatProduct([ 'values' => [ 'a_date' => [ ['locale' => null, 'scope' => null, 'data' => new \DateTimeImmutable('2000-01-01')], ] ] ]); // $formatted = [ // 'values' => [ // 'a_date' => [ // ['locale' => null, 'scope' => null, 'data' => '2000-01-01T00:00:00+0000'], // ] // ] // ];
Format metrics
The metrics represented as strings are converted to arrays with keys amount
and unit
. The unit can be before or after the amount. For instance :
$formatted = $apiBooster->formatProduct([ 'values' => [ 'a_metric' => [ ['locale' => 'fr_FR', 'scope' => null, 'data' => '15.56 KILO'], ['locale' => 'de_DE', 'scope' => null, 'data' => 'GRAM 18'], ] ] ]); // $formatted = [ // 'values' => [ // 'a_metric' => [ // ['locale' => 'fr_FR', 'scope' => null, 'data' => ['amount' => '15.56', 'unit' => 'KILO']], // ['locale' => 'de_DE', 'scope' => null, 'data' => ['amount' => '18', 'unit' => 'GRAM']], // ] // ] // ];
Format prices
The prices represented as strings are converted to arrays with keys amount
and currency
. The currency can be before or after the amount. The currency can be a symbol. For instance :
$formatted = $apiBooster->formatProduct([ 'values' => [ 'a_price_collection' => [ ['locale' => 'fr_FR', 'scope' => null, 'data' => '23 EUR'], ['locale' => 'de_DE', 'scope' => null, 'data' => '$24'], ['locale' => 'it_IT', 'scope' => null, 'data' => '15.75 €, 16 USD, GBP 8'], ] ] ]); // $formatted = [ // 'values' => [ // 'a_price_collection' => [ // ['locale' => 'fr_FR', 'scope' => null, 'data' => [['amount' => '23', 'currency' => 'EUR']]], // ['locale' => 'de_DE', 'scope' => null, 'data' => [['amount' => '24', 'currency' => 'USD']]], // ['locale' => 'de_DE', 'scope' => null, 'data' => [['amount' => '15.75', 'currency' => 'EUR'], ['amount' => '16', 'currency' => 'USD'], ['amount' => '8', 'currency' => 'GBP']]], // ] // ] // ];
What if my data can't be formatted?
If API Booster can't format your data, it won't be modified. No error is thrown. The goal is to let you call the API so that it returns you the actual error.
Installation
Once you have downloaded the ZIP file containing API Booster, activate your license key:
curl https://api.gumroad.com/v2/licenses/verify \ -d "product_permalink=akeneo-api-booster" \ -d "license_key=YOUR-LICENSE-KEY" \ -X POST
There is currently no simple distribution system. If enough customers are interested, I'll set up a private packagist. This would be more convenient. Contact me in case of need.
Go to the root directory of your project and unzip the file:
cd /path/to/my/project unzip api-booster-*.zip rm api-booster-*.zip mv api-booster-* api-booster
Edit your composer.json
to add API Booster's repository:
{ # ... "repositories": [ { "type": "path", "url": "./api-booster" # path where the folder "api-booster" is located relatively to your composer.json } ] }
Now you can require API Booster:
composer require "jjanvier/api-booster":"dev-master"
Don't worry about the dev-master
version. This is required as we use here a path repository, but the ZIP file you downloaded matches a real release.
And that's it! Now you are ready to configure API Booster.
Configuration
If your project is based on Symfony
Configuration
Activate the bundle ApiBoosterBundle
in the kernel.
# config/bundles.php <?php return [ //... Jjanvier\ApiBooster\Integration\Symfony\ApiBoosterBundle::class => ['all' => true], ];
Configure the caches you want to use in your framework configuration. You can use any number of cache solutions you want. The only requirement is that the cache pool must be named api_booster.cache.internal
. In the following example we’ll use the in memory array and the apcu adapters.
# config/packages/framework.yaml framework: cache: pools: api_booster.cache.internal: adapters: - 'cache.adapter.array' - 'cache.adapter.apcu'
Define the following environment variables in the root .env
file :
AKENEO_API_CLIENT_ID=client AKENEO_API_SECRET=secret AKENEO_API_USERNAME=username AKENEO_API_PASSWORD=password AKENEO_API_URL=url
And that’s it! You’re now ready to use ApiBooster.
Usage
You can retrieve the service api_booster
from the container and use it in your code. It will return an instance of the class Jjanvier\ApiBooster\Library\ApiBooster
. For instance :
$apiBooster = $this->getContainer()->get(‘api_booster’); $attribute = $apiBooster->getAttribute(‘my_attribute’);
A demo command is available to check everything is working well :
bin/console api_booster:demo-cache my_attribute
You have an example of a small Symfony application configured to work with API Booster in your vendor/jjanvier/api-booster/demo/symfony
folder.
If you use another framework than Symfony or no framework at all
Configuration and usage
You have an example of a small PHP application configured to work with API Booster in your vendor/jjanvier/api-booster/demo/vanilla
folder.
All you need to do is to build the API Booster instance via its factory :
$myCaches = [/* an array of PSR6 or Symfony contracts caches*/ ]; $logger = null; // a PSR logger if you want to debug $apiBooster = Jjanvier\ApiBooster\Integration\Vanilla\ApiBoosterFactory::build( $myCaches, $url, $clientId, $secret, $username, $password, $logger );
And that’s it! You’re now ready to use ApiBooster. For instance :
$attribute = $apiBooster->getAttribute(‘my_attribute’);