イントロダクション

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

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

アクセサーとミューテター

アクセサー定義

アクセサーを定義するにはアクセスしたいカラム名の「キャメルケース」が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 string
     */
    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();

デフォルトのタイムスタンプフォーマットは'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プロパティーは配列でキーにはキャストする属性名を指定し、値にはそのカラムに対してキャストしたいタイプを指定します。サポートしているキャストタイプはintegerrealfloatdoublestringbooleanobjectarraycollectiondatedatetimeです。

例としてデータベースには整数の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) {
    //
}

配列キャスト

arrayキャストタイプはシリアライズされたJSON形式で保存されているカラムを取り扱うときに特に便利です。たとえばデータベースにシリアライズ済みのJSONを持つTEXTフィールドがある場合、その属性に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();