Eloquent:シリアライゼーション
はじめに
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 serialization. * * @var array<string> */ 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`プロパティに追加できます。アクセサのPHPメソッドは「キャメルケース」を使用して定義されていますが、属性名は通常、「スネークケース」のシリアライズされた表現を使用して参照されることに注意してください。
<?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', ];}