简体   繁体   中英

Fields in Laravel Eloquent models

I am new to Laravel and Eloquent, so excuse me if this is a totally stupid question. I have been looking at how to create a model at both the documentation here and also another tutorial here (in the Creating Models using Eloquent ORM section) and I've noticed that the actual fields of the table are never mentioned, unless there is something specific about them (like having a relationship with another table, or not requiring mass assignment, or if they need to be hidden from JSON output etc.)

Are these fields being omitted on purpose and PHP just adds them when it performs the query using PDO with FETCH_OBJ turned on? If yes why is it that we do not explicitly put the fields in the model? Doesn't it help us to know what fields we have, and also IDEs such as PHPStorm to pop up the right auto-complete fields?

If they are actually required, what access level do they need to have?

Thanks.

Column names (fields) are not required in Eloquent models. As you pointed out, it is only necessary to define the functions which determine the relationships that a model has with others.

It isn't necessary to include them, because of the reason you mentioned (Laravel does a select * and then adds all of the returned rows to the model object as public properties). This is a process dubbed hydration and you can see exactly what is happening by digging into the Laravel source. Here's a summary of what happens:

  1. You call (for example), Users::find(123);
  2. Illuminate\\Database\\Eloquent\\Model::find() calls Illuminate\\Database\\Eloquent\\Builder::find()
  3. find() constructs the SELECT * FROM users WHERE id = 123 query and then returns the first result by calling Illuminate\\Database\\Eloquent\\Builder::first()
  4. first() adds LIMIT 1 by calling Illuminate\\Database\\Query\\Builder::take()
  5. Then first() sets the columns to be retrieved ( * by default) by calling Illuminate\\Database\\Eloquent\\Builder::get() .
  6. get() returns an Illuminate\\Database\\Eloquent\\Collection by using the return value of Illuminate\\Database\\Eloquent\\Builder::getModels()
  7. getModels() actually performs the query and then calls Illuminate\\Database\\Eloquent\\Model::newFromBuilder() for each row returned
  8. newFromBuilder() creates a new instance of the model and sets the columns (fields) by calling Illuminate\\Database\\Eloquent\\Model::setRawAttributes()

I've omitted some unrelated things such as eager loading to simplify the process, but this is basically what happens for each query.

You make a good point that knowing the fields beforehand can be helpful for autocompletion. Because of the nature of setRawAttributes() it is perfectly OK to declare all column names (fields) in your model (just make sure they are public). The convention, though (and for you sanity), is to omit them. Such declarations should be left to migration files .

After further examination of the source, it is not ok to declare the fields beforehand. This is because the actual attribute values are stored in an $attributes property and then accessed by the magic method __get() . The trouble here is that by defining the properties beforehand, you will prevent __get() from being called when you access the fields. Therefore, this is not an option.

However, there are ways to hint to editors (like PhpStorm) about the existence of properties without explicitly defining them .

There is another way to make phpstorm to auto-complete column name and avoid warning.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM