Fields in Laravel Eloquent models
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:
- You call (for example),
Users::find(123);
Illuminate\Database\Eloquent\Model::find()
callsIlluminate\Database\Eloquent\Builder::find()
find()
constructs theSELECT * FROM users WHERE id = 123
query and then returns the first result by callingIlluminate\Database\Eloquent\Builder::first()
first()
addsLIMIT 1
by callingIlluminate\Database\Query\Builder::take()
- Then
first()
sets the columns to be retrieved (*
by default) by callingIlluminate\Database\Eloquent\Builder::get()
. get()
returns anIlluminate\Database\Eloquent\Collection
by using the return value ofIlluminate\Database\Eloquent\Builder::getModels()
getModels()
actually performs the query and then callsIlluminate\Database\Eloquent\Model::newFromBuilder()
for each row returnednewFromBuilder()
creates a new instance of the model and sets the columns (fields) by callingIlluminate\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