#はじめに
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
{
/**
* 配列に含めない属性
*
* @var array
*/
protected $hidden = ['password'];
}
リレーションを隠すには、Eloquentモデルの$hiddenプロパティにリレーションメソッド名を追加してください。
または、visibleプロパティを使って、モデルの配列やJSONに含める属性の「許可リスト」を定義できます。$visible配列に含まれない属性は配列やJSONに変換される際に隠されます:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 配列に表示する属性
*
* @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
{
/**
* ユーザーが管理者かどうか判定する
*/
protected function isAdmin(): Attribute
{
return new Attribute(
get: fn () => 'yes',
);
}
}
アクセサをモデルの配列やJSON表現に常に追加したい場合は、モデルのappendsプロパティに属性名を追加します。属性名は通常、アクセサのPHPメソッドがキャメルケースでも、シリアライズ時のスネークケースで指定します:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* モデルの配列形式に追加するアクセサ
*
* @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メソッドをオーバーライドしてカスタマイズできます。このメソッドはデータベース保存時のフォーマットには影響しません:
/**
* 配列/JSONシリアライズ用に日付を準備する
*/
protected function serializeDate(DateTimeInterface $date): string
{
return $date->format('Y-m-d');
}
#属性ごとに日付フォーマットをカスタマイズする
モデルのキャスト宣言で個別のEloquent日付属性のシリアライズフォーマットを指定できます:
protected $casts = [
'birthday' => 'date:Y-m-d',
'joined_at' => 'datetime:Y-m-d H:00',
];