Good content takes time and effort to come up with.

Please consider supporting us by just disabling your AD BLOCKER and reloading this page again.







Accessors & Mutators In Laravel. Problem In Set Attribute While Saving/Updating Data & How To Resolve It


Share On     Share On WhatsApp     Share On LinkedIn


Many times you want the first_name or last_name to be capitalized while storing in your database. And sometimes you want to stored status like open/closed with a small case and when fetching you need to be capitalized.


This is easily achievable in Laravel and has feature named Accessors (What to do when accessing some field) & Mutators (What to do when saving/updating some field).


Prerequisites


I hope you have basic understanding of Laravel & know how to do CRUD (Create, Read, Update, Delete) operations.


Accessors (getColumnNameAttribute)


To define an accessor, create a getFirstNameAttribute method on your model where FirstName is the "studly" cased name of the column you wish to access, here its first_name as stored in your database table. This accessor will automatically called by Eloquent when you retrieve the value of the first_name from database table.


NOTE: Accessor starts with get and ends with Attribute. In between you will have column name in studly caps.


Following is the example of how to do it in MODEL


<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  public function getFirstNameAttribute($firstName)
  {
    return ucfirst($firstName);
  }
}


In the above example you can see that the $firstName attribute is passed and its returning capitalized name. You can name anything to your accessor method parameter.


In Controller

$user = App\Models\User::where('email', $email)->first();
/** Here the FirstName accessor is called automatically */
echo $user->first_name; 


You can also user accessor to return the value based on more than one fields. For example


public function getFullNameAttribute($firstName)
{
    return ucfirst($this->first_name) .' '. ucfirst($this->last_name);
}



Mutators (setColumnNameAttribute)


As I had said in the intro of this article, if you want to store some column name inside your database table with modified value. To define an mutator, create a setFirstNameAttribute method on your model where FirstName is the "studly" cased name of the column you wish to mutate, here its first_name as stored in your database table. This mutator will automatically called by Eloquent when you writing the value to first_name inside database table.


NOTE: Mutator starts with set and ends with Attribute. In between you will have column name in studly caps.


Following is the example of how to do it in MODEL


<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  public function setFirstNameAttribute($firstName)
  {
    $this->attributes['first_name'] = strtolower($firstName);
  }
}


As you can see from the above example the mutator is called by eloquent automatically when saving the record to database. Here I am passing $firstName as a parameter and as you see the and making it lowercase when saving


In Controller


When you store the data to user table automatically setFirstNameAttribute method is called.


App\Models\User::create([
  'first_name'  => request('first_name'),
  'last_name'   => request('last_name'),
  'email'       => request('email'),
]);



Problem When Updating Data In Eloquent Data


One of the problem what you face while using mutators is during updating the data.


The following is the normal process how you update the data in Laravel Eloquent


App\Models\User::where('email', $email)
  ->update([
    'first_name'  => request('first_name'),
    'last_name'   => request('last_name'),
    'email'       => request('email')
  ]);

There is no problem with the above query. But you will be wondering why the setFirstNameAttribute was not called on first_name attribute. And when you see your database table you will see that first_name column wont be in lowercase.


Reason: SET ATTRIBUTE wont work on insert. And SET ATTRIBUTE wont work on the update query as you ran above eloquent query. It works on collection for some reason.

To fix this issue while updating you can use the following way


$user = App\Models\User::where('email', $email)->first();
if($user){
  $user->update([
    'first_name'  => request('first_name'),
    'last_name'   => request('last_name'),
    'email'     => request('email')
  ]);
}


Tada! It woks like wonder.


Conclusion


With great power comes great responsibility and you can mess up sometimes and go wrong in few places too. So think before you want to it in your code.




Author Image
AUTHOR

Channaveer Hakari

I am a full-stack developer working at WifiDabba India Pvt Ltd. I started this blog so that I can share my knowledge and enhance my skills with constant learning.

Never stop learning. If you stop learning, you stop growing