メインコンテンツまでスキップ

エロクエント: シリアル化

はじめに

Laravelを使用してAPIを構築する際、モデルやリレーションを配列やJSONに変換する必要があります。Eloquentには、これらの変換を行う便利なメソッドが含まれており、モデルのシリアル化された表現に含まれる属性を制御する方法も提供されています。

注記

EloquentモデルやコレクションのJSONシリアル化をさらに強化する方法については、Eloquent APIリソースのドキュメントを参照してください。

モデルとコレクションのシリアル化

配列へのシリアル化

モデルとその読み込まれたリレーションシップを配列に変換するには、toArrayメソッドを使用する必要があります。このメソッドは再帰的であり、すべての属性とリレーション(リレーションのリレーションを含む)が配列に変換されます:

    use App\Models\User;

$user = User::with('roles')->first();

return $user->toArray();

attributesToArrayメソッドは、モデルの属性を配列に変換しますが、リレーションは変換されません:

    $user = User::first();

return $user->attributesToArray();

また、モデルのコレクション全体を配列に変換するには、コレクションインスタンスでtoArrayメソッドを呼び出すことができます:

    $users = User::all();

return $users->toArray();

JSONへのシリアル化

モデルをJSONに変換するには、toJsonメソッドを使用する必要があります。toArrayと同様に、toJsonメソッドも再帰的であり、すべての属性とリレーションがJSONに変換されます。また、PHPでサポートされている任意のJSONエンコーディングオプションを指定することもできます。

    use App\Models\User;

$user = User::find(1);

return $user->toJson();

return $user->toJson(JSON_PRETTY_PRINT);

または、モデルまたはコレクションを文字列にキャストすることもできます。これにより、モデルまたはコレクションの toJson メソッドが自動的に呼び出されます:

    return (string) User::find(1);

モデルやコレクションは文字列にキャストされるときに JSON に変換されるため、アプリケーションのルートやコントローラから Eloquent オブジェクトを直接返すことができます。Laravel は、Eloquent モデルやコレクションをルートやコントローラから返すときに自動的に JSON にシリアライズします:

    Route::get('users', function () {
return User::all();
});

リレーションシップ

Eloquent モデルが JSON に変換されると、ロードされたリレーションシップは自動的に JSON オブジェクトの属性として含まれます。また、Eloquent のリレーションシップメソッドは "キャメルケース" メソッド名で定義されていますが、リレーションシップの JSON 属性は "スネークケース" になります。

JSON から属性を非表示にする

モデルの配列や JSON 表現に含める属性(パスワードなど)を制限したい場合があります。そのためには、モデルに $hidden プロパティを追加します。$hidden プロパティの配列にリストされている属性は、モデルのシリアライズされた表現に含まれません:

    <?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = ['password'];
}

注記

リレーションシップを非表示にするには、Eloquent モデルの $hidden プロパティにリレーションシップのメソッド名を追加します。

また、visible プロパティを使用して、モデルの配列や JSON 表現に含める必要がある属性の "許可リスト" を定義することもできます。$visible 配列に存在しないすべての属性は、モデルが配列または JSON に変換されるときに非表示になります:

    <?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
/**
* The attributes that should be visible in arrays.
*
* @var array
*/
protected $visible = ['first_name', 'last_name'];
}

属性の可視性を一時的に変更する

特定のモデルインスタンスで通常非表示の属性を表示したい場合は、makeVisible メソッドを使用できます。makeVisible メソッドはモデルインスタンスを返します:

    return $user->makeVisible('attribute')->toArray();

同様に、通常表示されている属性を非表示にしたい場合は、makeHidden メソッドを使用できます。

    return $user->makeHidden('attribute')->toArray();

一時的にすべての表示または非表示属性をオーバーライドする場合は、それぞれ setVisible メソッドと setHidden メソッドを使用できます:

    return $user->setVisible(['id', 'name'])->toArray();

return $user->setHidden(['email', 'password', 'remember_token'])->toArray();

JSON に値を追加する

モデルを配列や JSON に変換する際に、データベースに対応する列がない属性を追加したい場合があります。そのためには、まずその値のために アクセサ を定義します:

    <?php

namespace App\Models;

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

class User extends Model
{
/**
* Determine if the user is an administrator.
*/
protected function isAdmin(): Attribute
{
return new Attribute(
get: fn () => 'yes',
);
}
}

アクセサを常にモデルの配列や JSON 表現に追加したい場合は、モデルの appends プロパティに属性名を追加します。属性名は通常、"snake case" シリアライズされた表現を使用して参照されますが、アクセサの PHP メソッドは "camel case" で定義されていることに注意してください:

    <?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = ['is_admin'];
}

appends リストに属性が追加されると、その属性はモデルの配列および JSON 表現に含まれます。appends 配列内の属性は、モデルで構成された visible および hidden 設定も遵守します。

実行時に追加する

実行時に、モデルインスタンスに append メソッドを使用して追加の属性を追加するか、setAppends メソッドを使用して指定されたモデルインスタンスの追加プロパティの配列全体をオーバーライドできます:

    return $user->append('is_admin')->toArray();

return $user->setAppends(['is_admin'])->toArray();

日付のシリアル化

デフォルトの日付形式のカスタマイズ

serializeDate メソッドをオーバーライドすることで、デフォルトのシリアル化形式をカスタマイズすることができます。このメソッドは、データベースに保存される日付のフォーマットに影響しません:

    /**
* Prepare a date for array / JSON serialization.
*/
protected function serializeDate(DateTimeInterface $date): string
{
return $date->format('Y-m-d');
}

属性ごとの日付形式のカスタマイズ

個々の Eloquent 日付属性のシリアル化形式をカスタマイズするには、モデルの キャスト宣言 で日付形式を指定します。

    protected function casts(): array
{
return [
'birthday' => 'date:Y-m-d',
'joined_at' => 'datetime:Y-m-d H:00',
];
}