ロード時にLaravel/Eloquentモデルにカスタム属性/プロパティを追加できるようにしたいと思います。これは RedBeanの$model->open()
メソッドで実現できるのと同じように。
たとえば、現時点では、私のコントローラには、次のものがあります。
public function index()
{
$sessions = EventSession::all();
foreach ($sessions as $i => $session) {
$sessions[$i]->available = $session->getAvailability();
}
return $sessions;
}
ループを省略して 'available'属性をすでに設定してデータを追加できるようにするとよいでしょう。
オブジェクトのロード時にこのプロパティを添付するために、ドキュメントに記載されているモデルイベントのいくつかを使用してみましたが、これまでのところ成功していません。
注:
$sessions
はAPIの一部としてJSONオブジェクトとして返されているため、テンプレートで$session->available()
のようなものを呼び出すことはできません。この問題は、Model
の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);
}
}
Laravel Eloquentドキュメントページの最後のもの は次のとおりです。
protected $appends = array('is_admin');
::toArray()
のようなメソッドを修正するような追加の作業なしに、自動的にそれを使って新しいアクセサをモデルに追加することができます。
getFooBarAttribute(...)
アクセサを作成し、foo_bar
を$appends
配列に追加するだけです。
getAvailability()
メソッドの名前をgetAvailableAttribute()
に変更すると、そのメソッドはアクセサになり、モデル上で->available
を使用して読み取ることができます。
ドキュメント: https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators
編集:あなたの属性は "仮想"であるため、それはあなたのオブジェクトのJSON表現にデフォルトで含まれていません。
しかし、私はこれを見つけました: - > toJson()が呼ばれたときにカスタムモデルアクセサが処理されませんでした?
属性を配列に返させるには、それを$ attributes配列のキーとして追加します。
class User extends Eloquent {
protected $attributes = array(
'ZipCode' => '',
);
public function getZipCodeAttribute()
{
return ....
}
}
私はそれをテストしませんでした、しかしあなたがあなたの現在の設定で試してみることはかなり簡単なはずです。
私は何か同じようなものを持っていました:私は自分のモデルの中に属性画像があります、これはStorageフォルダの中のファイルの場所を含みます。画像はbase64エンコードで返される必要があります
//Add extra attribute
protected $attributes = ['pictureData'];
//Make it available in the json response
protected $appends = ['pictureData'];
//implement the attribute
public function getPictureDataAttribute()
{
$file = Storage::get($this->picture);
$type = Storage::mimeType($this->picture);
return "data:" . $type . ";base64," . base64_encode($file);
}
modelでsetAttribute
関数を使ってカスタム属性を追加することができます
Usersテーブルにfirst_nameとlast_nameという2つのカラムがあり、フルネームを取得したいとしましょう。次のコードで達成できます。
class User extends Eloquent {
public function getFullNameAttribute()
{
return $this->first_name.' '.$this->last_name;
}
}
今、あなたはフルネームを得ることができます:
$user = User::find(1);
$user->full_name;
私の場合は、空の列を作成してそのアクセサを設定するとうまくいきました。私のアクセサはdobカラムからユーザの年齢を埋めます。 toArray()関数も機能しました。
public function getAgeAttribute()
{
return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}
私の購読モデルでは、購読が一時停止されているかどうかを知る必要があります。これが私のやり方ですpublic function getIsPausedAttribute() { $isPaused = false; if (!$this->is_active) { $isPaused = true; } }
ビューテンプレートでは、結果を取得するために$subscription->is_paused
を使用できます。
getIsPausedAttribute
はカスタム属性を設定するためのフォーマットです。
ビュー内の属性を取得または使用するためにis_paused
を使用します。