Add daily email for 06/04/25
This commit is contained in:
parent
4e7b79e77c
commit
a0d23ce355
1 changed files with 71 additions and 0 deletions
71
source/_daily_emails/2025-04-06.md
Normal file
71
source/_daily_emails/2025-04-06.md
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue