Цель: я хочу "украсить" Laravel Query Builder дополнительными функциями (без непосредственного изменения).
Пример проблемы: я постараюсь сделать это очень кратким. Я реализовал в своем декораторе get
метод:
public function get($columns = ['*'])
{
return $this->cache->get(implode('.', $columns), function () use ($columns) {
return $this->queryBuilder->get($columns);
});
}
Я также делегирую все вызовы методов, не реализованных в декораторе, построителю запросов.
public function __call($method, $parameters)
{
return call_user_func_array([$this->queryBuilder, $method], $parameters);
}
Как и следовало ожидать, при прямом вызове декоратора работает нормально. Но почти все привыкли объединять методы в цепочки при использовании Query Builder.
$queryBuilder = (new CachingDecorator( new QueryBuilder , $app['cache.store'] ));
// get all users
$queryBuilder->from('users')->get();
// get one user
$queryBuilder->from('users')->first(); // <-- delegates to get() internally
Проблема: результаты указанного выше вызова не кэшируются. Очевидно, потому что метод from
возвращает экземпляр Laravel Query Builder, а не мой декоратор.
Вопрос. Есть ли какой-нибудь полезный шаблон, который поможет решить эту проблему? Или это ограничение паттерна декоратора?
Моей первой мыслью было попытаться привязать $ this к другому объекту, как это можно сделать в Javascript. Я не думаю, что PHP позволяет это.
Лучшее решение, которое я могу придумать, включает в себя класс для сопоставления объекта построителя запросов с его декоратором (ами) и / или какой-то базовый декоратор, который повторно реализует почти каждый метод в объекте построителя запросов (не поклонник этого один, поскольку он полностью выбрасывает принцип СУХОЙ).
Дополнительные примечания. Я знаю, что могу обойти эту проблему, просто не объединяя вызовы методов в цепочку. Ежу понятно, правда? За исключением того, что неразумно просить каждого разработчика в команде избегать объединения своих вызовов вместе. Я бы предпочел решить эту проблему, чем обойти ее стороной.
$this->cache
является экземпляромIlluminate\Contracts\Cache\Repository
. То же, что и при использованииCache::get()
. - person Johnny   schedule 10.11.2015