diff --git a/source/_daily_emails/2025-04-06.md b/source/_daily_emails/2025-04-06.md new file mode 100644 index 000000000..bfc9be5e6 --- /dev/null +++ b/source/_daily_emails/2025-04-06.md @@ -0,0 +1,71 @@ +--- +title: Caching with decorators +date: 2025-04-06 +permalink: daily/2025/04/06/caching +tags: + - software-development + - drupal + - php +cta: ~ +snippet: | + TODO +--- + +As well as [working with different versions of an API][0], I was able to use the same technique I wrote about yesterday to easily add a cacheable version of the API client. + +As they all implement the same `ApiClientInterface`, I can inject and decorate a client with another client, making one solely responsible for caching the result from the API whilst keeping the API interaction logic separate (aka [the Decorator design pattern][1]). + +Here's an example based on the code I wrote: + +```php +final class CacheableApiClient implements ApiClientInterface { + + /** + * The cache duration in seconds. + */ + private const CACHE_DURATION = 3600; + + public function __construct( + private readonly ApiClientInterface $client, + private readonly TimeInterface $time, + private readonly CacheBackendInterface $cache, + ) { + } + + public function getResults(): Collection { + $key = $this->getCacheKey(); + + $cache = $this->cache->get($key); + + if ($cache !== FALSE) { + return $cache->data; + } + + $result = $this->client->getResults(); + + $this->cache->set( + cid: $key, + data: $result, + expire: $this->time->getRequestTime() + self::CACHE_DURATION, + ); + + return $result; + } + +} +``` + +Nothing in this instance is specific to either version of the API. + +This client is only concerned with retrieving and saving cache data, and delegating any other logic to the original version. + +With this approach, I can switch between `V1ApiClient`, `V2ApiClient` or any other version with the same methods without having to reimplement caching as that's handled within the `CacheableApiClient`. + +But what if I don't want to interact with the API at all? + +For local development, I have a `FakeApiClient` that returns a static response that I can work with. + +The possibilities are endless. + +[0]: {{site.url}}/daily/2025/04/05/strategies +[1]: {{site.url}}/daily/2022/12/08/the-decorator-design-pattern