Leavel Eloquent Accessors and Mutators

In this Blog, we'll understand mutators and accessors of the Eloquent ORM in the Laravel framework by examples.

Laravel, Accessors, and Mutators allow us to alter data while saving and fetching. As per the name, Accessor alters data while accessing and Mutators modify data while saving. The major difference between an accessor and Mutator is that data modification in an accessor is temporary while in a mutator modify data is stored in the database.

For example, if we want to store a user name in upper case in our database then we can define a mutator for that so that when we save the model it will automatically convert the name into uppercase and also store the name in uppercase.

Suppose we store the user's name as first name and last name. We want to display full user names across various pages then we need to add them manually Right!!! But by using accessors we can create an attribute that merges it and use that attribute whenever required.

Create Accessors and Mutators in a Laravel Model

Let's take a practical example. Here, we will create Post Model and define Accessor and Mutator on it.

To create a model, enter the below command into your terminal:

php artisan make:model Post -m

It will create a Model and migration file for Post. Let's modify them one by one:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
    protected $fillable = [
        'title',
        'content',
        'user',
    ];
}
database/migrations/timestamp_posts_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content');
            $table->string('user');
            $table->timestamps();
        });
    }
   public function down()
    {
        Schema::dropIfExists('posts');
    }
}

Here, we have created a basic database structure for our posts table now it's time to migrate it. Enter below command to migrate :

php artisan migrate
Titles generally use title case. which means, the first character of each word in a string to uppercase. Here, we will take user input into free text and store it in lowercase using Mutator and use title in title case while displaying using accessors.

Let's define a Mutator and accessor for the title attribute. The Mutator will be automatically called when we attempt to set the value of the title attribute on the model and Accessor will convert title into title case while fetching data.

Syntax :

//Accessor
public function get{AtributeName}Attribute($value)
{
    return converted value;
}

//Mutator
public function set{AttributeName}Attribute($value)
{
    $this->attributes['attribute name'] = conveted value;
}
In syntax, replace {AttributeName} with your field name. But be careful and use camelcase for attribute name. For example, if you want to define user_name then function name should be getUserNameAttribute for Accessor and setUserNameAttribute for Mutator.

Let's modify our model to set Accessor and Mutator for title attribute. So make below changes into Post Model :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
    protected $fillable = [
        'title',
        'content',
        'user',
    ];

    public function getTitleAttribute($value)
    {
        return ucfirst($value);
    }

    public function setTitleAttribute($value)
    {
        $this->attributes['title'] = strtolower($value);
    }
}

Checking Accessor and Mutator

Let's check whether our Accessor and Mutator functions are working or not. Let's use a controller to check it.

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class TestController extends Controller
{
    public function checkAccessor(){
        $post = Post::find(1);

        echo $post->title;

        exit;
    }
    public function checkMutator(){
        $post = new Post();
        $post->title = 'Foo Bar';
        $post->content = "Test";
        $post->user = "test";
        $post->save();

        echo $post;
        exit;
    }
}

let's define the route too.

<?php

use App\Http\Controllers\TestController;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Route::get('check-accessor',[TestController::class,'checkAccessor');
Route::get('check-mutator',[TestController::class,'checkMutator');

Testing our Functionality

Now we are ready to test our functionality. open the terminal and run below command :

php artisan serve

Open this URL in a browser and it will show location information.

http://127.0.0.1:8000/check-accessor
http://127.0.0.1:8000/check-mutator

When you open check-accessor then it will find first record and display it. While check-mutator method will create new records from controller values.