为什么 Eloquent\Builder 不从 Laravel 中的 Query\Builder 继承?

Sim*_*son 5 php laravel

在 Laravel 中, Eloquent \Builder类将每次调用发送到它不需要内部Query\Builder 的方法。对我来说,这听起来像是继承。有人知道为什么他们没有实现它以便Eloquent\Builder扩展Query\Builder?我第一次注意到它的原因是我在 IDE 中遇到了“调用未定义方法”错误,尽管代码工作正常,这是我认为的魔法方法的诅咒。

作为参考,这里是来自Eloquent\Builder.

/**
 * The base query builder instance.
 *
 * @var \Illuminate\Database\Query\Builder
 */
protected $query;

protected $passthru = array(
    'toSql', 'lists', 'insert', 'insertGetId', 'pluck', 'count',
    'min', 'max', 'avg', 'sum', 'exists', 'getBindings',
);

public function __call($method, $parameters)
{
    if (method_exists($this->model, $scope = 'scope'.ucfirst($method)))
    {
        return $this->callScope($scope, $parameters);
    }
    else
    {
        $result = call_user_func_array(array($this->query, $method), $parameters);
    }

    return in_array($method, $this->passthru) ? $result : $this;
}
Run Code Online (Sandbox Code Playgroud)

Tho*_*eng 5

我将从我的结论开始。我认为它只是设计得很糟糕。

让我做一些解释,并回复 @Simon Bengtsson 接受的答案

我无意冒犯任何人,只是想表达我的想法。


实际上,继承的全部意义在于它们具有相似的特性,但您想添加一个额外的层来放置一些扩展功能。显然,扩展的“子”类会比“父”类知道更多(比如了解 Eloquent Model)

对我来说,“建设者”就是建设者。毕竟,两者实际上都在构建查询,无论其检查或观察什么条件。这就是构建器的目的(至少从我看来)。所以它位于同一层(除了Eloquent\Builder有一些额外的功能)。

当前的实现覆盖了一些方法的性质,例如 where() (基本上是 中的方法Query\Builder,相同的名称,相同的参数)。它还添加了一些方法,最终调用像 where() 这样的方法。这都是关于继承的。如果我调用 where(),并且它存在于子类中,则会调用子类方法。如果没有,就会调用父类的方法。


如果您假设想要使用一些新的 NoSQL DB 并简单地编写一个符合 Query\Builder 签名的插入类,那么以后,解耦低级和 ORM 级组件就会变得更加困难。

@西蒙·本特森

我不明白脱钩是如何变得困难的。您所要做的就是编写一个新类Query\MongoDBBuilder,它与Query\Builder. 如果您担心,您始终可以使类“实现”接口。如果你问我,实际上目前的方式更难解耦,因为现在“哪些功能被覆盖,哪些没有”非常混乱。

在某些情况下,我确实鼓励类解耦,但如果我要解耦这个类(我认为这里没有必要),我会这样做:

  • Eloquent\Model
  • Eloquent\Adapter(这是某种中间层,您可以在其中放置连接设置等)
  • Eloquent\Builder extends Query\Builder(这是 Query\Builder 的“包装器”,因此它可以做更多的事情,但实现相同的目标)

子类还可以访问父类上受保护的属性,以便 Eloquent\ChildOfQueryBuilder 可以自由地依赖 Query\Builder 的低级实现,并可以与其耦合。

@西蒙·本特森

这就是继承的全部要点。您将能够访问受保护的属性来覆盖父级提供的功能。让我们从另一个角度来看,如果您需要访问这些变量来修改功能怎么办?事实上,作者声明这些成员“受保护”已经暗示他已经准备好另一个类来扩展它。这是使其“受到保护”的唯一目的,对吗?

这就是为什么在继承父类之前您必须确切地知道它在做什么,因为这可能很危险。


我之所以给出这么长的解释是因为我正在尝试修改 Eloquent 的一些功能。我一直在研究days的实现(3个神类:Eloquent\ModelEloquent\BuilderQuery\Builder)。分层和锯齿真的很混乱。Model由于其实现不佳,扩展该类需要我重新声明几乎等效的函数。但这不是主题。

总之,如果你问“为什么”,我实际上会说(现在我知道人们会踢我)它只是设计和实施不佳。