我有一个Laravel项目,我正在按照Laravel upgrade guide从5.3升级到5.4。
在指南中,它说创建方法已移至Builder类,并且该方法应称为新方法$model = static::query()->create($attributes);
。除了升级指南中记录的内容外,互联网上还有很多问题,例如here和here。
我不了解的部分是为什么他们仍然将覆盖方法指定为静态方法。新的create方法不再是静态的(因此进行了新的调用),但是所有示例仍然定义了一个静态方法来覆盖它。如果这样做,PHPStorm会给我以下(预期)错误:
无法使非静态方法Builder-> create([attributes:array = []])静态
为什么示例(包括官方文档)将其覆盖为静态?
假设有一个对其他所有人都有效的原因,为什么我的工作不成功?
答案 0 :(得分: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();
});
}
它基本上具有相同的作用,但更适合构建器,但是显着的区别是它不是静态的,因为模型上所有类似静态的调用都被转发到{{1 }} 实例。
如果您之前确实在子类中重写了该方法,然后在某个时候调用了Builder
,由于父级实际上没有创建对象,因此这可能不再起作用,因此,parent::create
的替代代码被建议。在实践中,调用static::query()->create(...)
也可能会起作用,但这很难读,并且由于无法调用$this->__call('create', ...)
而使IDE进行重构,因此很麻烦。
现在最后一点是Builder::create
上也有Model
。 @mixin Builder
表示一个类在当前类中基本上是混合在一起的,以扩展其功能,并用于向IDE暗示当它以非标准OOP方式发生时(例如,@mixin
和__call
)。这导致您的IDE认为您正在__callStatic
上create
上超载,这是因为IDE认为Builder
与Builder
混合在一起,但实际情况并非如此。完全混为一谈,而是混为一谈(据我所知,PhpStorm在处理这个概念时遇到了麻烦)
就这样。我希望这是有道理的。