Introduce
Accessors and Murators allow you to format Eloquent properties when we retrieve or add new models. For example, when adding a user you want before adding, it automatically encrypts the value of the password before being saved to the database or retrieving a name from the database as a print. flowers then accessors
and murators
will help us to do this. In addition, Eloquent can also automatically convert the date field into a Carbon instance or convert a text into a json data type.
1. Define an Accessors
In a nutshell, accessors
will help us format the data when we get data from the database. Suppose we have the name
field in the user
table and want to retrieve the data it will be in uppercase. First we need to create a method to define this in the User
model as get
+ tên trường in hoa chữ cái đầu
+ Attribute
. In this case, the method written will be getNameAttribute
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">App</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Database Eloquent Model</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Authenticatable</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">getNameAttribute</span> <span class="token punctuation">(</span> <span class="token variable">$value</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">strtoupper</span> <span class="token punctuation">(</span> <span class="token variable">$value</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span> |
Now try to see how the result is, you will create a route
as follows:
1 2 3 4 5 6 | Route <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'/accessors'</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$user</span> <span class="token operator">=</span> App <span class="token package">User</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">find</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">name</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Now go to localhost: 8000 / accessors and see the results.
Or you can even define a new property with existing attributes, for example:
1 2 3 4 5 | <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">getFullNameAttribute</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token double-quoted-string string">" <span class="token interpolation"><span class="token punctuation">{</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">first_name</span> <span class="token punctuation">}</span></span> <span class="token interpolation"><span class="token punctuation">{</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">last_name</span> <span class="token punctuation">}</span></span> "</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
The procedure is similar
1 2 | <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">fullname</span> <span class="token punctuation">;</span> |
2. Defining a murators.
Unlike accessors
, murators
used to format data before saving it in a database. To define a murators
closely resembles accessors
only difference is that the prefix will be set
. For example, we will format the name
field to be not capitalized before being saved into the database. So the method here will be setNameAttribute
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">namespace</span> <span class="token package">App</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Database Eloquent Model</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Authenticatable</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">setNameAttribute</span> <span class="token punctuation">(</span> <span class="token variable">$value</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">attributes</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'name'</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">strtolower</span> <span class="token punctuation">(</span> <span class="token variable">$value</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
To test we also create a route with the following content:
1 2 3 4 5 6 7 | Route <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'/murators'</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$user</span> <span class="token operator">=</span> App <span class="token package">User</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">find</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">name</span> <span class="token operator">=</span> <span class="token double-quoted-string string">"CCC"</span> <span class="token punctuation">;</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">save</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">name</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
To check if the data is saved properly or not, open the php artisan tinker
to check AppUser::find(1)
, we will see that the value of the newly saved name
field will be ccc
.
3. Date Murators
By default, Eloquent will automatically convert the created_at
and update_at
fields to the Carbon instance, and it provides a lot of useful functions. We can also add date properties by using $date
in the model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">App</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Database Eloquent Model</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span> <span class="token punctuation">{</span> <span class="token comment">/** * The attributes that should be mutated to dates. * * @var array */</span> <span class="token keyword">protected</span> <span class="token variable">$dates</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'seen_at'</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> </span> |
When a field is of type date
you can set its value to a UNIX timestamp
, date string (Ymd), date-time string or an instance of Carbon, and the value of the date will automatically be stored in the database.
Date formats
By default the timestamps are formatted as Ymd H:i:s
, you can dateFormat
this format by using the dateFormat
property in the model, this property will reformat as the date data type to be saved. in the database.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">App</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Database Eloquent Model</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$dateFormat</span> <span class="token operator">=</span> <span class="token single-quoted-string string">'Y-m-d'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> </span> |
4. Attribute Casting
The $cast
attribute helps convert attributes to normal data types. The $cast
attribute is usually an array where the key is the name of the property to be transferred and value is the type of data you want to transfer. The data types that the $cast
attribute supports: integer, real, float, double, decimal:<digits>, string, boolean, object, array, collection, date, datetime, and timestamp
. For example, we have the is_admin
property stored in the database as 0
and 1
with integer
data types but you want to use it as a boolean
data type, do the following
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">App</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Database Eloquent Model</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$casts</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'is_admin'</span> <span class="token operator">=</span> <span class="token operator">></span> <span class="token single-quoted-string string">'boolean'</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> </span> |
Then we use is_admin
as a property of boolean
data type
1 2 3 4 5 6 | <span class="token variable">$user</span> <span class="token operator">=</span> App <span class="token package">User</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">find</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">is_admin</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
Custom cast
You can define your own cast
attribute by creating an implements class from the CastsAttributes
interface. One thing to note is that this newly created class must have two get
and set
methods with different tasks. The get
method is used to convert data in the database to the cast
data type that you define, while the set
method has the opposite task to convert the converted data into the original data type to store in the database. For example, we custom cast
attribute is json data type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">App Casts</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Contracts Database Eloquent CastsAttributes</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">Json</span> <span class="token keyword">implements</span> <span class="token class-name">CastsAttributes</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token variable">$model</span> <span class="token punctuation">,</span> <span class="token variable">$key</span> <span class="token punctuation">,</span> <span class="token variable">$value</span> <span class="token punctuation">,</span> <span class="token variable">$attributes</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">json_decode</span> <span class="token punctuation">(</span> <span class="token variable">$value</span> <span class="token punctuation">,</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">set</span> <span class="token punctuation">(</span> <span class="token variable">$model</span> <span class="token punctuation">,</span> <span class="token variable">$key</span> <span class="token punctuation">,</span> <span class="token variable">$value</span> <span class="token punctuation">,</span> <span class="token variable">$attributes</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">json_encode</span> <span class="token punctuation">(</span> <span class="token variable">$value</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span> |
Then we will use it in the model.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">App</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">App Casts Json</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Database Eloquent Model</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$casts</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'options'</span> <span class="token operator">=</span> <span class="token operator">></span> Json <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token keyword">class</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> </span> |
Array & JSON Casting
Cast
array Cast
very useful when we use them with a column saved as json.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">App</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Database Eloquent Model</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$casts</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'options'</span> <span class="token operator">=</span> <span class="token operator">></span> <span class="token single-quoted-string string">'array'</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> </span> |
When declared like this, we will use and process the data as an array in PHP. When you set the value for the options
attribute, the given array will automatically be converted back into JSON to store:
1 2 3 4 5 6 7 8 9 10 | <span class="token variable">$user</span> <span class="token operator">=</span> App <span class="token package">User</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">find</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$options</span> <span class="token operator">=</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">options</span> <span class="token punctuation">;</span> <span class="token variable">$options</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'key'</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token single-quoted-string string">'value'</span> <span class="token punctuation">;</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">options</span> <span class="token operator">=</span> <span class="token variable">$options</span> <span class="token punctuation">;</span> <span class="token variable">$user</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">save</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Date Casting
When using cast
with a date and datetime data type, we can reformat it
1 2 3 4 | <span class="token keyword">protected</span> <span class="token variable">$casts</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'created_at'</span> <span class="token operator">=</span> <span class="token operator">></span> <span class="token single-quoted-string string">'datetime:Y-m-d'</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> |
Query Time Casting
Sometimes you can even use cast
in your queries
1 2 3 4 5 6 7 8 9 | <span class="token keyword">use</span> <span class="token package">App Post</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">App User</span> <span class="token punctuation">;</span> <span class="token variable">$users</span> <span class="token operator">=</span> User <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">select</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'users.*'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'last_posted_at'</span> <span class="token operator">=</span> <span class="token operator">></span> Post <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">selectRaw</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'MAX(created_at)'</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">whereColumn</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'user_id'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'users.id'</span> <span class="token punctuation">)</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
The last_posted_at
attribute is based on the result of the selectRaw statement, it would be more reasonable if we set the data type for last_posted_at
be of a date type, simply by using the withCasts
method.
1 2 3 4 5 6 7 8 | <span class="token variable">$users</span> <span class="token operator">=</span> User <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">select</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'users.*'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'last_posted_at'</span> <span class="token operator">=</span> <span class="token operator">></span> Post <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">selectRaw</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'MAX(created_at)'</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">whereColumn</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'user_id'</span> <span class="token punctuation">,</span> <span class="token single-quoted-string string">'users.id'</span> <span class="token punctuation">)</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">withCasts</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'last_posted_at'</span> <span class="token operator">=</span> <span class="token operator">></span> <span class="token single-quoted-string string">'date'</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
You can also see how other usefulness the cast
attribute brings here .