【问题标题】:Decorators and method chaining装饰器和方法链
【发布时间】:2016-02-10 16:18:34
【问题描述】:

目标:我想用附加功能“装饰” Laravel 的查询构建器(不直接修改它)。

示例问题:我会尽量保持简短。我在装饰器上实现了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 不允许这样做。

我能想出的最佳解决方案包括一个将查询构建器对象映射到其装饰器的类,和/或某种基本装饰器,它重新实现查询构建器对象中的几乎所有方法(不是喜欢这个,因为它完全抛弃了 DRY 原则)。

附加说明:我知道我可以通过不将方法调用链接在一起来回避这个问题。没脑子吧?除非要求团队中的每个开发人员避免将他们的调用链接在一起是不合理的。我更愿意解决这个问题而不是回避它。

【问题讨论】:

  • 你没有使用 laravel 缓存系统有什么原因吗?
  • @jfadich 我是。 $this-&gt;cacheIlluminate\Contracts\Cache\Repository 的一个实例。与使用 Cache::get() 相同。

标签: php laravel decorator method-chaining


【解决方案1】:

您应该从 __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;
}

【讨论】:

  • (facepalm) 一切都那么简单明了。哈哈。我喜欢你的头在哪里。很确定这正是我所需要的。谢谢大佬!
  • 所以我了解__call() 返回的内容,如果注入/装饰方法返回装饰对象,则将返回 current 对象(装饰器) .否则,结果是装饰对象方法返回的任何内容。这样做是为了帮助链接,否则尝试链接装饰器中的方法将在链中的第一个方法之后失败,因为返回的对象将“跳跃”到装饰的对象堆栈(朝向根对象)。我理解正确吗?
猜你喜欢
  • 2010-10-16
  • 2012-09-11
  • 2020-01-11
  • 2010-10-14
  • 2014-01-14
  • 1970-01-01
  • 2016-07-04
  • 2014-06-25
  • 2021-11-27
相关资源
最近更新 更多