扩展Laravel create():为什么文档说要将非静态方法覆盖为静态?

问题描述 投票:2回答:1

我有一个Laravel项目,我正在从Laravel upgrade guide升级到5.3到5.4。

在指南中它说创建方法已经移动到Builder类,并且这个方法应该被称为新方法$model = static::query()->create($attributes);。除了在升级指南中记录之外,互联网上还有许多问题,例如herehere

我不明白的部分是为什么他们仍然将覆盖方法指定为静态。新的create方法不再是静态的(因此是新的调用),但是,所有示例仍然定义了一个静态方法来覆盖它。如果我这样做,PHPStorm会给我以下(预期)错误:

无法使非静态方法Builder-> create([attributes:array = []])静态

为什么示例(包含官方文档)将其覆盖为静态?

假设它适用于其他所有人的原因,为什么不开采工作呢?

php laravel upgrade
1个回答
0
投票

所以这里有一个非常简短的解释,这里发生了什么。 5.3及更早版本中的Laravel雄辩模型在其自己的类中使用create方法作为静态函数。这是来源:

public static function create(array $attributes = [])
{
    $model = new static($attributes);
    $model->save();
    return $model;
}

同时该模型具有以下__call定义。

public function __call($method, $parameters)
{
    if (in_array($method, ['increment', 'decrement'])) {
        return $this->$method(...$parameters);
    }
    return $this->newQuery()->$method(...$parameters);
}

这意味着将在Builder对象的新实例上调用未在模型上定义的每个函数调用。

在5.4他们认为create似乎更适合Builder而不是模型本身所以他们在那里制作了这个方法:

public function create(array $attributes = [])
{
    return tap($this->newModelInstance($attributes), function ($instance) {
        $instance->save();
    });
}

它基本上做同样的事情,但它更适合构建器,但是显着的区别是它不是静态的,因为模型上的所有类似静态的调用都被转发到Builder实例。

如果你之前在子类中覆盖了方法,然后在某个时候调用了parent::create,那么这可能不再有效,因为父级实际上没有创建,因此建议使用static::query()->create(...)的替代代码。在实践中调用$this->__call('create', ...)也可能会工作,但这很难阅读,并会搞乱IDE进行重构,因为它是一个无法察觉的调用Builder::create

现在最后一点是Model也有@mixin Builder@mixin表示一个类基本上混合在当前类中以扩展其功能,并且用于向IDE提示当它以非标准OOP方式发生时(例如在这种情况下使用__call__callStatic)。这导致你的IDE认为你在create上超载Builder由于IDE认为BuilderModel混在一起然而现实是它并没有完全混合而是混合在一起作为静力学(据我所知) PhpStorm处理这个概念有困难)

就是这样。我希望这是有道理的。

© www.soinside.com 2019 - 2024. All rights reserved.