API Booster

1.0.1
Developed by Julien Janvier Inc
Akeneo PIM compatibility
Enterprise Edition (SaaS) Supported
Enterprise Edition (PaaS)
Growth Edition Not supported
Community Edition
Extension type
Bundle
More info
Extension version
1.0.1
Price: €399.00

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 :

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 , 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’);