Laravel Eloquent 模型中的字段

20

我对Laravel和Eloquent都是新手,所以请原谅我问这样一个愚蠢的问题。 我一直在查看文档这里 和另一个教程这里(在使用Eloquent ORM创建模型部分),我注意到除非有特定的情况(例如与另一个表存在关系,或不需要进行大规模的赋值操作,或者需要从JSON输出中隐藏它们等),否则从未提到表的实际字段。

这些字段是有意省略的吗?PHP只在使用PDO执行查询并打开FETCH_OBJ时才添加它们吗? 如果是,为什么我们不在模型中明确指定字段?这难道不能帮助我们知道有哪些字段,也帮助像PHPStorm这样的IDE显示正确的自动完成字段吗?

如果实际上需要这些字段,它们需要什么访问级别?

谢谢。

2个回答

21

Eloquent模型中的列名(字段)并非必需。正如你所指出的那样,只需要定义函数来确定该模型与其他模型之间的关系即可。

不必包含它们,因为你提到的原因(Laravel执行了一个select *,然后将返回的所有行添加到模型对象中作为公共属性)。这个过程被称为hydration,你可以通过深入研究Laravel源代码来了解发生的事情。以下是发生的概述:

  1. 你调用(例如),Users::find(123);
  2. Illuminate\Database\Eloquent\Model::find()调用Illuminate\Database\Eloquent\Builder::find()
  3. find()构造了SELECT * FROM users WHERE id = 123查询,然后通过调用Illuminate\Database\Eloquent\Builder::first()返回第一个结果
  4. first()通过调用Illuminate\Database\Query\Builder::take()添加了LIMIT 1
  • first()调用Illuminate\Database\Eloquent\Builder::get()来设置要检索的列(默认为*)。
  • get()使用Illuminate\Database\Eloquent\Builder::getModels()的返回值,返回一个Illuminate\Database\Eloquent\Collection
  • getModels()实际执行查询,然后对返回的每一行都调用Illuminate\Database\Eloquent\Model::newFromBuilder()
  • newFromBuilder()创建模型的新实例,并通过调用Illuminate\Database\Eloquent\Model::setRawAttributes()来设置列(字段)。
  • 为了简化过程,我省略了一些无关的内容,如贪婪加载,但基本上每个查询都会发生这些事情。

    您说得很有道理,提前知道字段名称可以帮助自动补全。由于setRawAttributes()的特性,完全可以在模型中声明所有列名(字段)(确保它们是public)。然而,为了您的清晰和明了,请按照惯例省略它们,这样的声明应该留给迁移文件

    经过进一步检查源代码后发现,事先声明字段是不可行的。这是因为实际的属性值存储在$attributes属性中,然后通过魔术方法__get()访问。问题在于,如果事先定义了这些属性,您将阻止访问字段时调用__get()。因此,这不是一个选项。

    但是,有方法向编辑器(如PhpStorm)暗示属性的存在,而无需显式定义它们


    1
    感谢您详细的回复。遗憾的是,我不能像PDO的fetchObject()一样使用它,我可以指定类名并且它会为我的特定类实例化。事实上,我正在使用PhpStorm,它似乎支持使用phpdoc标签的提示,因此这是一个良好的解决方法,以获得适当的IDE支持。 - jbx
    如果你真的想要那个功能,你可以继承Eloquent类,它实际上是Illuminate\Database\Eloquent\Model(在app/config/app.php中查找别名数组,并确保将Eloquent别名设置为您的Eloquent子类的正确FQN),并定义setRawAttributes()以像那样运作,但这可能会比使用phpdoc标签更复杂。 - Bailey Parker
    1
    是的,这会变得过于复杂,超出了我想要实现的范围。我只想让事情保持简洁易维护。过多地偏离标准方法也可能使我无法查找解决方案或在这里提问。phpdoc 标签似乎不错,如果通过 Notepad++ 或 Vi 等不太智能的编辑器打开模型,它们也有用,可以指示模型具有哪些魔法字段。感谢您的见解! - jbx
    2
    那么我应该如何知道模型的字段呢? - James Lin

    2

    有另一种方法可以让PhpStorm自动完成列名并避免警告。

    /**
     * @property string $title Title of article
     */
    class Article extends Eloquent
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接