Декораторы и метод цепочки

Цель: Я хочу «украсить» Laravel Query Builder дополнительными функциями (без непосредственного изменения).

Пример задачиЯ постараюсь сделать это очень кратким. Я реализовал get Метод на моем декораторе:

public function get($columns = ['*'])
{
return $this->cache->get(implode('.', $columns), function () use ($columns) {
return $this->queryBuilder->get($columns);
});
}

Я также делегирую все вызовы методов, не реализованных в декораторе, в Query Builder.

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 позволяет это.

Лучшее решение, которое я могу придумать, включает в себя класс для сопоставления объекта построителя запросов с его декоратором (-ами) и / или своего рода базовый декоратор, который повторно реализует почти каждый метод в объекте построителя запросов (не фанат этого один, поскольку он полностью выбрасывает принцип СУХОЙ в окно).

Дополнительные примечанияЯ знаю, что могу обойти проблему, просто не объединяя вызовы методов. Ежу понятно, верно? За исключением того, что нет смысла просить каждого разработчика в команде избегать цепочки своих вызовов вместе. Я бы предпочел решать эта проблема, чем обойти его.

0

Решение

Вы должны вернуть свой декоратор из __call метод:

public function __call($method, $parameters)
{
$result = call_user_func_array([$this->queryBuilder, $method], $parameters);

return $result === $this->queryBuilder ? $this : $result;
}

Если вы используете PHP 5.6+, вы можете использовать оператор распространения, чтобы немного это исправить:

public function __call($method, $parameters)
{
$result = $this->queryBuilder->$method(...$parameters);

return $result === $this->queryBuilder ? $this : $result;
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]