Skip to content

Eloquent: シリアライズ

イントロダクション

Laravelを使用してAPIを構築する際、モデルとそのリレーションを配列やJSONに変換する必要があることがよくあります。Eloquentには、これらの変換を行うための便利なメソッドが含まれており、モデルのシリアライズされた表現にどの属性を含めるかを制御できます。

Note

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'];
}

Note

リレーションを隠蔽するには、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配列内の属性は、モデルで設定されたvisiblehiddenの設定も尊重します。

実行時に追加

実行時にモデルインスタンスに追加の属性を追加するように指示するには、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 function casts(): array
{
    return [
        'birthday' => 'date:Y-m-d',
        'joined_at' => 'datetime:Y-m-d H:00',
    ];
}

ユーザーノート