イントロダクション

アクセサとミューテタはモデルの取得や値を設定するときに、Eloquent属性のフォーマットを可能にします。たとえばLaravelの暗号化を使いデータベース保存時に値を暗号化し、Eloquentモデルでアクセスする時には自動的にその属性を復元するように設定できます。

カスタムのアクセサやミューテタに加え、Eloquentは日付フールドを自動的にCarbonインスタンスにキャストしますし、テキストフィールドをJSONにキャストすることもできます。

アクセサとミューテタ

アクセサの定義

アクセサを定義するには、アクセスしたいカラム名が「studlyケース」でFooの場合、getFooAttributeメソッドをモデルに作成します。以下の例では、first_name属性のアクセサを定義しています。first_name属性の値にアクセスが起きると、Eloquentは自動的にこのアクセサを呼び出します。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザのファーストネームを取得
     *
     * @param  string  $value
     * @return string
     */
    public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }
}

ご覧の通り、アクセサにはそのカラムのオリジナルの値が渡されますので、それを加工し値を返します。アクセサの値にアクセスするには通常通りに、モデルインスタンスのfirst_name属性へアクセスしてください。

$user = App\User::find(1);

$firstName = $user->first_name;

ミューテタの定義

ミューテタを定義するにはアクセスしたいカラム名がFooの場合、モデルに「ローワーキャメルケース」でsetFooAttributeメソッドを作成します。今回もfirst_name属性を取り上げ、ミューテタを定義しましょう。このミューテタはモデルのfirst_name属性へ値を設定する時に自動的に呼びだされます。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザのファーストネームを設定
     *
     * @param  string  $value
     * @return void
     */
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtolower($value);
    }
}

ミューテタは属性に設定しようとしている値を受け取りますのでこれを加工し、Eloquentモデルの$attributes内部プロパティーへ加工済みの値を設定します。ではSallyfirst_name属性へ設定してみましょう。

$user = App\User::find(1);

$user->first_name = 'Sally';

上記の場合、setFirstNameAttributeメソッドが呼び出され、Sallayの値が渡されます。このミューテタはそれから名前にstrtolowerを適用し、その値を$attributes内部配列へ設定します。

日付ミューテタ

デフォルトでEloquentはcreated_atupdated_atカラムをCarbonインスタンスへ変換します。CarbonはPHPネイティブのDateTimeクラスを拡張しており、便利なメソッドを色々と提供しています。モデルの$datesプロパティーをオーバーライドすることで、どのフィールドを自動的に変形するのか、逆にこのミューテタを適用しないのかをカスタマイズできます。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 日付を変形する属性
     *
     * @var array
     */
    protected $dates = [
        'created_at',
        'updated_at',
        'deleted_at'
    ];
}

カラムが日付だと推定される場合、値はUnixタイムスタンプ、日付文字列(Y-m-d)、日付時間文字列、それにもちろんDateTimeCarbonインスタンスを値としてセットでき、日付は自動的に正しくデータベースへ保存されます。

$user = App\User::find(1);

$user->deleted_at = Carbon::now();

$user->save();

前記の通り$datesプロパティーにリストした属性を取得する場合、自動的にCarbonインスタンスへキャストされますので、その属性でCarbonのメソッドがどれでも使用できます。

$user = App\User::find(1);

return $user->deleted_at->getTimestamp();

Dateフォーマット

デフォルトのタイムスタンプフォーマットは'Y-m-d H:i:s'です。タイムスタンプフォーマットをカスタマイズする必要があるなら、モデルの$dateFormatプロパティを設定してください。このプロパティは日付属性がデータベースにどのように保存されるかと同時に、モデルが配列やJSONにシリアライズされる時のフォーマットを決定します。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * モデルの日付カラムの保存形式
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

属性キャスト

モデルの$castsプロパティーは属性を一般的なデータタイプへキャストする便利な手法を提供します。$castsプロパティーは配列で、キーにはキャストする属性名を指定し、値にはそのカラムに対してキャストしたいタイプを指定します。サポートしているキャストタイプはintegerrealfloatdoublestringbooleanobjectarraycollectiondatedatetimetimestampです。

例としてデータベースには整数の01で保存されているis_admin属性を論理値にキャストしてみましょう。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ネイティブなタイプへキャストする属性
     *
     * @var array
     */
    protected $casts = [
        'is_admin' => 'boolean',
    ];
}

これでデータベースには整数で保存されていてもis_admin属性にアクセスすれば、いつでも論理値にキャストされます。

$user = App\User::find(1);

if ($user->is_admin) {
    //
}

配列とJSONのキャスト

arrayキャストタイプは、シリアライズされたJSON形式で保存されているカラムを取り扱うときに特に便利です。たとえば、データベースにシリアライズ済みのJSONを持つJSONTEXTフィールドがある場合、その属性にarrayキャストを追加すれば、Eloquentモデルにアクセスされた時点で自動的に非シリアライズ化され、PHPの配列へとキャストされます。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ネイティブなタイプへキャストする属性
     *
     * @var array
     */
    protected $casts = [
        'options' => 'array',
    ];
}

キャストを定義後、options属性にアクセスすると自動的に非シリアライズされPHP配列になります。options属性へ値をセットすると配列は保存のために自動的にJSONへシリアライズされます。

$user = App\User::find(1);

$options = $user->options;

$options['key'] = 'value';

$user->options = $options;

$user->save();