Php 装饰器和方法链接

Php 装饰器和方法链接,php,laravel,decorator,method-chaining,Php,Laravel,Decorator,Method Chaining,目标:我想用附加功能“装饰”Laravel的查询生成器(无需直接修改) 示例问题:我会尽量简短。我在我的装饰器上实现了一个get方法: public function get($columns = ['*']) { return $this->cache->get(implode('.', $columns), function () use ($columns) { return $this->queryBuilder->get($columns

目标:我想用附加功能“装饰”Laravel的查询生成器(无需直接修改)

示例问题:我会尽量简短。我在我的装饰器上实现了一个
get
方法:

public function get($columns = ['*'])
{
    return $this->cache->get(implode('.', $columns), function () use ($columns) {
        return $this->queryBuilder->get($columns);
    });
}
我还将所有对decorator上未实现的方法的调用委托给查询生成器

public function __call($method, $parameters)
{
    return call_user_func_array([$this->queryBuilder, $method], $parameters);
}
$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
正如您所期望的那样,直接致电装饰师时效果良好。但在使用查询生成器时,几乎每个人都习惯于将方法链接在一起

public function __call($method, $parameters)
{
    return call_user_func_array([$this->queryBuilder, $method], $parameters);
}
$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
$queryBuilder=(新的CachingDecorator(新的queryBuilder,$app['cache.store']);
//获取所有用户
$queryBuilder->from('users')->get();
//获取一个用户

$queryBuilder->from('users')->first();// 您应该通过
\u调用
方法返回decorator:

public function\u调用($method,$parameters)
{
$result=call_user_func_数组([$this->queryBuilder,$method],$parameters);
返回$result===$this->queryBuilder?$this:$result;
}
如果您使用的是PHP 5.6+,则可以使用spread操作符稍微清理一下:

public function\u调用($method,$parameters)
{
$result=$this->queryBuilder->$method(…$parameters);
返回$result===$this->queryBuilder?$this:$result;
}

你有什么理由不使用laravels缓存系统吗?@jfadich我有
$this->cache
illumb\Contracts\cache\Repository
的一个实例。与使用
Cache::get()
(facepalm)一样,这一切都非常简单和清晰。哈哈,我喜欢你的脑袋。我很确定这正是我需要的。谢谢你,伙计!因此我理解
\uu call()
返回的是什么,如果注入/修饰方法返回修饰对象,那么将返回当前对象(修饰器)。否则,结果就是修饰对象方法返回的结果。这样做是为了帮助链接,否则尝试在decorator中链接方法将在链中的第一个方法之后失败,因为返回的对象将“跳跃”到经过修饰的对象堆栈(朝向根对象)。我理解正确吗?