There is a lot going on with Laravel's Eloquent ORM, but to start things off in this series, we will actually start things off and look at how Eloquent Models boot up and construct themselves.
For this tutorial, we will use this model as our example.
class Post extends Eloquent
{
$fillable = ['title', 'content'];
}
This is so that we are looking at just the default behavior of Eloquent before we start hacking things.
Now we will look at what happens when you call new Post(['post.title' => 'First Post', 'content' => 'lorem'])
.
First we dive into __construct
:
The First thing that happens is that we check to see if this Model checks if it has been booted.
It does this by checking the booted
static property on the parent Eloquent class with an array key of Post
in this case.
Since this the first time we are constructing an instance of our Post
model, we need to boot
it.
Now in boot
we will have to do some mild trickery:
Essentially, boot
goes through the Post
model and finds all of the mutators using a RegEx and stores it into the mutatorCache
on Eloquent in a Post
keyed array.
Then we go ahead and set booted['Post']
to true so we will not have to perform this again the next time we need an instance of Post
.
Finally, in a regular constructor, we only call fill
with the attributes passed in to the constructor.
In fill
we will go through each of our attributes and do the following.
First, we check if the attribute has a dot syntax for the key.
This is used to remove any table names that may have been included such as post.title
and then changes it to title
.
Now we check if the attribute is allowed within mass assignment by calling isFillable
.
In isFillable
, we ceheck a few different ways that mass assignment could be handled.
First we want to see if the model is set to be unguarded
: if so, we allow assignment.
Next we check if the attribute is in the fillable
array, then we once again allow assignment.
Then we check if it isGuarded
where we check if the key is in the guarded
array or if guarded
contains a splat array('*')
(which is the default): if so, then we do not allow mass assignment.
Finally if fillable
is empty we return true
unless the key starts with an underscore which is a convention list hidden attributes common in Rails.
If we found the key to be unfillable, we check to see if the model is totallyGuarded
.
Essentially, this means that if fillable
is empty and guarded
is a splat, then we will throw a MassAssignmentException.
This means that if you do not modify the fillable
or guarded
properties, MassAssignmentExceptions will be thrown when you try to call fill
.
But if we allow the attribute to be filled, then we need to setAttribute
.
Here we check for mutators in the mutatorCache
from before.
If there is a match, then we call this custom mutator which can contain any logic that we want.
Next we check if the key is in the dates
array.
If so, we set the value to an instance of Carbon
which is a powerful extention of PHP's Date object.
At the end of this, we set the key within the attributes
array to the value.
Finally, we return this instance to the user and our Eloquent Model is entirely booted up. Note, that the constructor deals in no way with relationships, the database, or modification of data.