Как я могу получить шаблон репозитория с кэшированием в Silverstripe 4? - PullRequest
0 голосов
/ 13 января 2019

У меня есть сторонний 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. Как я мог бы пойти дальше и реализовать это?

Попытка достичь чего-то подобного https://laracasts.com/discuss/channels/laravel/repository-pattern-with-caching-laravel?#reply=398497 в серебряной полосе 4

1 Ответ

0 голосов
/ 15 января 2019

Если вы не хотите разделять свои реализации 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...