ロード時に Laravel / Eloquent モデルにカスタム属性を追加しますか? 質問する

ロード時に Laravel / Eloquent モデルにカスタム属性を追加しますか? 質問する

Laravel/Eloquent モデルがロードされたときに、カスタム属性/プロパティを追加できるようにしたいと思います。

たとえば、現時点では、私のコントローラーには次のものがあります。

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

ループを省略して、「available」属性をすでに設定して入力しておくことができれば便利です。

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

ノート:

  • 「available」は基になるテーブル内のフィールドではありません。
  • $sessionsAPIの一部としてJSONオブジェクトとして返されるため、$session->available()テンプレートのようなものを呼び出すことはできません。

ベストアンサー1

Modelこの問題は、のtoArray()メソッドが、基になるテーブルの列に直接関連しないアクセサーを無視するという事実によって発生します。

テイラー・オットウェルが述べたようにここ「これは意図的なものであり、パフォーマンス上の理由によるものです。」ただし、これを実現する簡単な方法があります。

class EventSession extends Eloquent {

    protected $table = 'sessions';

    public function availability()
    {
        return new Attribute(
            get: fn () => $this->calculateAvailability()
        );  
    }
}

Laravel バージョン < 8:

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

class EventSession extends Eloquent {

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

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

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);    
    }

}

おすすめ記事