見出し画像

Laravel 学習記録 #007 アクセサ、ミューテータを学ぶ

Laravelのアクセサ、ミューテータについて学習したものをまとめてます。

アクセサ、ミューテータとは?

  • Eloquentモデルでデータを加工する機能

  • アクセサは、データベースの値を取得するときに値を加工できるメソッド(テーブルのフィールドに対応するプロパティを上書きして取得できる機能)

  • ミューテータはデータベースに値を設定する前に、値を変更または加工するためのメソッド(値を設定する処理を上書きして設定する機能)

アクセサの使い方

アクセサを使用するにはモデルに
get<任意の命名>Attribute
の名前でメソッドを作成します。

public function getXXAttribute(){
	// 処理
	return 値;
}

任意の命名の箇所を既存のプロパティ名とすることで、取得結果を上書き
既存のプロパティにはない命名とすることで、その名前で使えるようなります。

やってみる

マイグレーションファイルを下記のようにして「チームテーブル」を作成して確認してみます。

public function up(): void
    {
        Schema::create('teams', function (Blueprint $table) {
            $table->id();
            $table->string('team_name');
            $table->timestamps();
        });
    }

任意の命名のパターン
アクセサで、取得するチーム名に対して「アクセサで付与された説明」という文字列を追加してみます。
getTeamNameAddDescriptionAttributeメソッドを作成
処理としては取得のteam_nameに文字列を追加しただけです。

class Team extends Model
{
    use HasFactory;

    // アクセサ
    public function getTeamNameAddDescriptionAttribute(){
        return 'アクセサで付与された説明:' . $this->team_name;
    }
}

コントローラーで確認してみます。
アクセサで定義したやつを呼び出す際には、キャメルケースの命名をスネークケースに変換することで、他のプロパティ同様呼び出せます。
(定義がgetAaaBbbAttribute()の場合は、aaa_bbbとする)

Team::first()->teamName_add_description

結果確認

class ModelTestController extends Controller
{
    public function index() {
        dd(Team::first()->teamName_add_description); 
    }
}

結果
"アクセサで付与された説明:チームA"


既存の命名のパターン
既存のプロパティを変更するには
get<プロパティ名>Attribute()
として、プロパティに引数を渡す必要があります。

team_nameプロパティを変更してみます。

// アクセサ(既存のプロパティを変更)
    public function getTeamNameAttribute($value) {
        return "アクセサで既存のプロパティを変更:" . $value;
    }

では、コントローラーで確認してみます。
既存のプロパティを変更しているので、通常の呼び方でOKです。

class ModelTestController extends Controller
{
    public function index() {
        // アクセサでteam_nameに説明文を追加
        // 呼び出す際にはgetAaaBbbAttribute()の「AaaBbb」をスネークケースに変換
        // dd(Team::first()->teamName_add_description); 


        // 既存のプロパティを変更
        dd(Team::first()->team_name); 
    }
}


結果
"アクセサで既存のプロパティを変更:チームA"

このように、取得結果を加工することが可能です。
データベースで0,1などの値を管理し、表示には文字列のラベルを表示したい。なんてときは特に活躍しそうですよね。


ミューテータの使い方

ミューテータを使用するにはモデルに
set<任意の命名>Attribute
の名前でメソッドを作成し引数(渡された値)をセットします。

public function setXXAttribute(引数){
	// 処理
	return 値;
}

任意の命名の箇所を既存のプロパティ名とすることで、値を上書きし
既存のプロパティにはない命名とすることで、その名前で使えるようなります。

やってみる

アクセサ同様「チームテーブル」で試します。

任意の命名のパターン
ミューテータで、登録するチーム名に対して「ミューテータで付与された説明」という文字列を追加してみます。
setTeamNameAddDescriptionAttributeメソッドを作成
処理としては登録のteam_nameに文字列を追加しただけです。

class Team extends Model
{

    // アクセサ
    public function setTeamNameAddDescriptionAttribute($value) {
        return $this->attributes['team_name'] = 'ミューテータで付与された説明:' . $value;
    }
}

登録処理で確認してみます。
アクセサで定義したやつを使う際には、アクセサ同様キャメルケースの命名をスネークケースに変換してよびます。

team_name_add_description

結果確認

class ModelTestController extends Controller
{
    public function store() {

        // ミューテーターで登録時に加工
        $team = new Team();
        $team->team_name_add_description = "Aチーム";
        $team->save();

        dd($team);
    }
}


結果
#attributes: array:4 [▼
    "team_name" => "ミューテーターで付与された説明:Aチーム"
    "updated_at" => "2023-10-07 01:17:03"
    "created_at" => "2023-10-07 01:17:03"
    "id" => 4
  ]

登録後のteam_nameの値がミューテータで設定した値になっていることがわかります。

既存の命名のパターン
既存のプロパティを変更するには
set<プロパティ名>Attribute()
として、プロパティに引数を渡す必要があります。

team_nameプロパティを変更してみます。

// ミューテータ(既存のプロパティを変更)
    public function setTeamNameAttribute($value) {
        return $this->attributes['team_name'] = 'ミューテータで既存プロパティを変更:' . $value;
    }

では、コントローラーで確認してみます。
既存のプロパティを変更しているので、通常のセットでOKです。

class ModelTestController extends Controller
{
    public function store() {

        // 既存のプロパティを変更
        $team = new Team();
        $team->team_name = "Aチーム";
        $team->save();
    }
}


結果
#attributes: array:4 [▼
    "team_name" => "ミューテーターで既存プロパティを変更:Aチーム"
    "updated_at" => "2023-10-07 01:20:38"
    "created_at" => "2023-10-07 01:20:38"
    "id" => 6
  ]


このように、登録する値を加工することが可能です。
パスワード登録でハッシュ化したい時、なんかに使えそうですね。


アクセサ、ミューテータ、カスタムコレクションはLaravelのModelを使い倒すために抑えておきたい機能ですね。
ちなみに取得時にはアクセサ→カスタムコレクションの順で機能しているようでした。






この記事が気に入ったらサポートをしてみませんか?