Laravelのアクセサとミューテターが何かとコードの書き方といつ使うか

Laravelのアクセサとミューテターが何かとコードの書き方といつ使うか

110 回閲覧されました

みなさんこんにちは、jonioです。

今回はLaravelのアクセサとミューテターについてのメモになります。

おすすめ参考書

基礎力を上げるのに一番おすすめです。

この記事で知れること

下記になります。

  • アクセサとミューテターとは何か
  • コードの書き方
  • いつ使うか

Laravelのバージョン

8系以前と9系以降が対応しています。

8系以前と9系以降で書き方が変わるのでそれについても解説します。

アクセサとミューテターとは何か

下記になります。

  • アクセサ : データを取得する際にDBのデータを加工できる
  • ミューテター : データをDBに保存する際にデータを加工して保存できる

具体的にコードを見た方がイメージできるので次はコードを見ます。

8系以前のコードの書き方

<?php

namespace App\Models;

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

class User extends Model
{
    use HasFactory;
    
    //アクセサ
    public function getNameAttribute($value)
    {
        return ucfirst($value);
    }

    // ミューテータ
    public function setNameAttribute($value)
    {
        $this->attributes['name'] = strtolower($value);
    }
}

アクセサを使う時のメソッド名は「get⚪︎Attribute」(13行目)と決まっています。

「⚪︎」は存在しているカラム名を使います。

「⚪︎」の最初の文字は大文字にします、単語が複数繋がっていても最初の文字は大文字にします。

またメソッド名を「getNameAttribute」と書いた場合はカラム名を小文字にしてアクセスできます。

今回だと「name」です。

単語が複数あって例えば「getNameKanaAttribute」とした場合のカラム名は単語と単語の間に「_」を付けて「name_kana」でアクセスできます。

usersテーブルのidカラムが1のnameカラムの値(jonioとします)にアクセサを使って呼び出してみます。

下記のコードを書けば呼び出しができます。

$user = User::find(1);

dd($user->name);

// 出力結果は「Jonio」

アクセサを書いた時に「$value」がありました。

public function getNameAttribute($value)     //←の$value
{
    return ucfirst($value);     //←の$value
}

これはカラム名(上記のコードの場合はname)になります。

ミューテターを使う時のメソッド名は「set⚪︎Attribute」(19行目)と決まっています。

メソッドの命名規則はアクセサの時と同じです。

下記のコードでnameカラムの値の保存をしますが自動的に値を整形して保存します。

$user = User::find(1);

$user->name = 'Jonio';
$user->save();

// 保存した値は「jonio」

ミューテターのメソッドに出てくる「$value」はアクセサの時と同じです。

9系以降のコードの書き方

9系以降の書き方は私の感覚ではコードが見やすくなりました。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Attribute; //←この行を書く

class User extends Model
{
    public function name(): Attribute // 「: Attribute」を書く
    {
        return new Attribute(
            //アクセサ
            get: function ($value) {
                return ucfirst($value);
            },
            //ミューテター
            set: function ($value) {
                return strtolower($value);
            },
        );
    }
}

大きな変更点はアクセサとミューテターを1つのメソッドにまとめている点です。

11行目のメソッド名の「name」はカラム名です。

15行目の「get」・19行目の「set」は8系以前のメソッド名の名残だと思います。

getとsetの部分ですがアロー関数で書くこともできます。

public function name(): Attribute
{
    return new Attribute(
        
        
        //↓がアロー関数で書いた場合
        get: fn($value) => ucfirst($value),
        set: fn($value) => strtolower($value),
        //ここまでがアロー関数
        
        
    );
}

いつ使うか

絶対に使わないといけないということではありません。

ただミューテターを使うと整形の処理を別のメソッドに切り分けることができるのでコードの可読性が上がります。

<?php

namespace App\Models;

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

class User extends Model
{
    //別の処理
    public function xxxxx()
    {
    }
    
    
    //nameカラムの処理
    public function name(): Attribute
    {
        return new Attribute(
            get: function ($value) {
                return ucfirst($value);
            }
        );
    }
}

またアクセサを使うとテンプレートでデータの整形をして表示するのをモデルで行うことができるのでテンプレートのコードを読むのが楽になります。

ミューテター・アクセサの切り分けをすることができるのがメリットだと個人的に思いました。