Если вы не хотите разделять свои реализации UserRepository
и CachedUserRepository
, вы можете просто добавить кеширование в UserRepository
:
use Psr\SimpleCache\CacheInterface;
class UserRepository implements UserRepositoryInterface
{
protected $client;
protected $cache;
private static $dependencies = [
'Cache' => '%$' . CacheInterface::class . '.userrepository',
];
public function __construct(Client $client)
{
$this->client = $client;
}
public function getAll()
{
if (!$this->cache->get('fetchUsers')) {
$users = $this->client->fetchUsers();
$this->cache->set('fetchUsers', $users);
}
return $this->cache->get('fetchUsers');
}
public function setCache(CacheInterface $cache)
{
$this->cache = $cache;
return $this;
}
}
И некоторые настройки YAML для регистрации кеша:
SilverStripe\Core\Injector\Injector:
Psr\SimpleCache\CacheInterface.userrepository:
factory: SilverStripe\Core\Cache\CacheFactory
constructor:
namespace: userrepository
Если вы хотите разделить реализации таким же образом, как в статье, на которую вы ссылаетесь, вы можете сделать что-то похожее на то, что написано в статье, но вам нужно будет определить свой собственный метод взаимодействия с UserRepository
, так как SilverStripe не имеет такого вида API из коробки.
Например, что-то вроде этого:
class CachedUserRepository implements UserRepositoryInterface
{
protected $repository;
protected $cache;
private static $dependencies = [
'Cache' => '%$' . CacheInterface::class . '.userrepository',
];
public function __construct(UserRepository $repository)
{
$this->repository = $repository;
}
public function getAll()
{
if (!$this->cache->get('fetchUsers')) {
$users = $this->repository->getAll();
$this->cache->set('fetchUsers', $users);
}
return $this->cache->get('fetchUsers');
}
public function setCache(CacheInterface $cache)
{
$this->cache = $cache;
return $this;
}
}
Полагаю, вы бы создали его так:
$repository = Injector::inst()->create(CachedUserRepository::class, [
Injector::inst()->get(UserRepository::class),
]);
Обратите внимание, что важно использовать Injector для создания экземпляров ваших классов, чтобы регистрация внедрения через $dependencies
была зарегистрирована после создания.
Для согласованности с шаблонами внедрения зависимостей в SilverStripe вы также можете захотеть внедрить Client
в UserRepository
таким же образом, а также вставить UserRepository
в CachedUserRepository
таким же образом (конструкторы удалены, но не показаны в этих примерах.
UserRepository:
private static $dependencies = [
'Client' => '%$' . Client::class,
];
public function setClient(Client $client)
{
$this->client = $client;
return $this;
}
CachedUserRepository:
private static $dependencies = [
'Cache' => '%$' . CacheInterface::class . '.userrepository',
'Repository' => '%$' . UserRepository::class,
];
public function setRepository(UserRepository $repository)
{
$this->repository = $repository;
return $this;
}
Теперь Injector позаботится обо всех внедрениях зависимостей, поэтому ваша реализация будет выглядеть следующим образом:
$repository = Injector::inst()->get(CachedUserRepository::class);
Вы могли бы пойти еще дальше (это общий шаблон в SilverStripe 4) и определить конкретную реализацию для вашего интерфейса, поэтому реализации не нужно знать, какой класс будет использоваться:
# File: app/_config/repositories.yml
SilverStripe\Core\Injector\Injector:
UserRepositoryInterface:
# Define the repository you want by default
class: CachedUserRepository
И теперь вы можете получить свой репозиторий (по умолчанию кэшированный) следующим образом:
$repository = Injector::inst()->get(UserRepositoryInterface::class);