moneybird-php-client
moneybird-php-client copied to clipboard
Feature request: Implement PSR-6 compliant caching mechanism
Results from the Moneybird API are easily cacheable because of the synchronization API and because most (all?) entities have a version attribute. It would therefore make sense to integrate support for a PSR-6 compatible cache into this package to speed up queries and prevent users from making too many requests to the API.
Preferable, the user could specify a prefix for the cache key.
This would require the following work to be done:
- Adding
version
to the attribute list of all entities that support synchronization. - Checking if all entities that support synchronization actally use the
Synchronize
trait. - Updating the
getAll()
method to load items from and save items to the cache if the entity supports synchronization.
Currently, it is possible to implement something similar using the following code. However, this requires modifying the output of the ->attributes()
method, which does not return raw data that can cached and used with ->collectionFromResult(...)
later.
<?php
namespace App\Service;
use Picqer\Financials\Moneybird\Moneybird;
use Psr\Cache\CacheItemPoolInterface;
class MoneybirdCache
{
public function __construct(
private readonly Moneybird $moneybird,
private readonly CacheItemPoolInterface $cache
) {}
public function getAll(string $type, array $filters): array
{
$results = [];
$repository = $this->moneybird->$type();
$versions = $repository->listVersions($filters);
$idsToFetch = [];
foreach ($versions as $version)
{
$versionCacheItem = $this->cache->getItem('moneybird.'. $type .'.'. $version->id);
if ($versionCacheItem->isHit())
{
$cacheResult = $versionCacheItem->get();
if ($cacheResult['version'] == $version->version)
{
$results[] = $cacheResult;
continue;
}
}
$idsToFetch[] = $version->id;
}
$results = $repository->collectionFromResult($results);
for ($i = 0; $i < count($idsToFetch); $i += 100)
{
$fetchedObjects = $repository->getVersions(array_slice($idsToFetch, $i, 100, false));
foreach ($fetchedObjects as $object)
{
$results[] = $object;
$versionCacheItem = $this->cache->getItem('moneybird.'. $type .'.'. $object->id);
$attributes = self::normalizeAttributes($object->attributes());
$versionCacheItem->set($attributes);
$this->cache->save($versionCacheItem);
}
}
return $results;
}
private static function normalizeAttributes(array $attributes): array
{
$normalizedAttributes = [];
foreach ($attributes as $key => $value)
{
if (is_scalar($value))
{
$normalizedAttributes[$key] = $value;
}
elseif (is_array($value))
{
$normalizedAttributes[$key] = self::normalizeAttributes($value);
}
elseif ($value instanceof Model)
{
$normalizedAttributes[$key] = $value->attributes();
}
}
return $normalizedAttributes;
}
}