我有一个第三方API,可用来从中获取用户及其详细信息。如何在Silverstripe 4中通过缓存实现存储库模式?
我有一个名为UserRepositoryInterface的接口
interface UserRepositoryInterface
{
public function getAll();
}
UserRepository,与API交互以获取用户及其详细信息
class UserRepository implements UserRepositoryInterface
{
protected $client;
public function __construct(Client $client)
{
$this->client = $client;
}
public function getAll()
{
return $this->client->fetchUsers();
}
}
我知道我们需要一个CachedUserRepository来从缓存中获取用户(如果存在),否则从API目录中获取。我将如何实施呢?
尝试在Silverstripe 4中实现类似https://laracasts.com/discuss/channels/laravel/repository-pattern-with-caching-laravel?#reply=398497的功能
答案 0 :(得分:2)
如果您不想分离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
如果您想要以类似于所链接文章中的方式来分离实现,则可以执行与文章中类似的操作,但是您需要定义自己的与{{1}进行交互的方法},因为SilverStripe没有现成的API。
例如,如下所示:
UserRepository
我想您可以这样实例化它:
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;
}
}
请注意,使用Injector实例化您的类很重要,以便在构造后通过$repository = Injector::inst()->create(CachedUserRepository::class, [
Injector::inst()->get(UserRepository::class),
]);
注册依赖项注入。
为了与SilverStripe中的依赖项注入模式保持一致,您可能还希望以相同的方式将$dependencies
注入到Client
中,以及将UserRepository
注入到{{ 1}}的用法相同(删除了构造函数,但这些示例中未显示。
UserRepository:
UserRepository
CachedUserRepository:
CachedUserRepository
现在Injector将为您处理所有依赖项注入,因此您的实现应如下所示:
private static $dependencies = [
'Client' => '%$' . Client::class,
];
public function setClient(Client $client)
{
$this->client = $client;
return $this;
}
您可以再走一步(这是SilverStripe 4中的常见模式),并为您的接口定义一个具体的实现,因此该实现不需要知道将要使用哪个类:
private static $dependencies = [
'Cache' => '%$' . CacheInterface::class . '.userrepository',
'Repository' => '%$' . UserRepository::class,
];
public function setRepository(UserRepository $repository)
{
$this->repository = $repository;
return $this;
}
现在您可以像这样获取存储库(默认情况下为缓存):
$repository = Injector::inst()->get(CachedUserRepository::class);