1. ホーム
  2. php

[解決済み] ロード時にLaravel / Eloquentモデルにカスタム属性を追加しますか?

2022-04-17 17:48:05

質問

Laravel/Eloquentのモデルがロードされたときに、カスタム属性/プロパティを追加できるようにしたいのです。 RedBeanの $model->open() メソッドを使用します。

例えば、今現在、私のコントローラでは、以下のようになっています。

public function index()
{
    $sessions = EventSession::all();
    foreach ($sessions as $i => $session) {
        $sessions[$i]->available = $session->getAvailability();
    }
    return $sessions;
}

ループを省略して、'available' 属性がすでに設定され、入力されるようにできるといいのですが。

ドキュメントに記載されているモデルイベントのいくつかを使って、オブジェクトがロードされたときにこのプロパティをアタッチしようとしましたが、今のところ成功しません。

注意事項

  • 'available'は基礎となるテーブルのフィールドではありません。
  • $sessions は、APIの一部としてJSONオブジェクトとして返されるため、以下のような呼び出しが行われます。 $session->available() をテンプレートで使用することはできません。

解決方法は?

この問題の原因は Model 's toArray() メソッドは、基礎となるテーブルのカラムに直接関係しないアクセサは無視します。

Taylor Otwell が述べたように ここで しかし、これを簡単に実現する方法があります。

class EventSession extends Eloquent {

    protected $table = 'sessions';
    protected $appends = array('availability');

    public function getAvailabilityAttribute()
    {
        return $this->calculateAvailability();  
    }
}

適切なアクセサを追加していれば、$appends プロパティにリストされた属性は、自動的にモデルの配列または JSON 形式に含まれます。

古い回答です(Laravelバージョン< 4.08の場合)。

私が発見した最良の解決策は、このメソッドをオーバーライドすることです。 toArray() メソッドを使用して、明示的に属性を設定します。

class Book extends Eloquent {

    protected $table = 'books';

    public function toArray()
    {
        $array = parent::toArray();
        $array['upper'] = $this->upper;
        return $array;
    }

    public function getUpperAttribute()
    {
        return strtoupper($this->title);    
    }

}

または、カスタムアクセサがたくさんある場合は、それらをすべてループして適用します。

class Book extends Eloquent {

    protected $table = 'books';

    public function toArray()
    {
        $array = parent::toArray();
        foreach ($this->getMutatedAttributes() as $key)
        {
            if ( ! array_key_exists($key, $array)) {
                $array[$key] = $this->{$key};   
            }
        }
        return $array;
    }

    public function getUpperAttribute()
    {
        return strtoupper($this->title);    
    }

}