Добавить пользовательский атрибут в модель Laravel / Eloquent при загрузке?

Я бы хотел добавить пользовательский атрибут / свойство в модель Laravel / Eloquent, когда он загружен, подобно тому, как это может быть достигнуто с помощью метода $model->open() RedBean .

Например, на данный момент у меня в контроллере есть:

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

Было бы неплохо пропустить цикл и установить уже установленный и заполненный атрибут «Доступный».

Я попытался использовать некоторые из событий модели, описанных в документации, чтобы прикрепить это свойство, когда объект загружается, но пока не достиг успеха.

Заметки:

  • «Доступно» не является полем в базовой таблице.
  • $sessions возвращается как объект JSON как часть API, поэтому вызов типа $session->available() в шаблоне не является опцией

Проблема связана с тем, что метод toArray() игнорирует любые аксессоры, которые напрямую не связаны с столбцом в базовой таблице.

Как сказал Тейлор Отуэлл: «Это преднамеренно и по соображениям производительности». Однако есть простой способ добиться этого:

 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 doc :

 protected $appends = array('is_admin'); 

Это можно использовать автоматически для добавления новых аксессуаров к модели без какой-либо дополнительной работы, например, для модификации таких методов, как ::toArray() .

Просто создайте getFooBarAttribute(...) accessor и добавьте массив foo_bar в $appends .

Если вы переименуете метод getAvailability() в getAvailableAttribute() ваш метод станет аксессуаром, и вы сможете прочитать его, используя ->available прямо на вашей модели.

Документы: https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators

EDIT: поскольку ваш атрибут «виртуальный», он не включен по умолчанию в представлении JSON вашего объекта.

Но я нашел это: пользовательские адаптеры модели не обрабатывались при вызове -> toJson ()?

Чтобы заставить атрибут быть возвращенным в массиве, добавьте его как ключ к массиву $ attributes.

 class User extends Eloquent { protected $attributes = array( 'ZipCode' => '', ); public function getZipCodeAttribute() { return .... } } 

Я не тестировал его, но должен быть довольно тривиальным для вас, чтобы попробовать в вашей текущей настройке.

вы можете использовать функцию setAttribute в Model для добавления настраиваемого атрибута

У меня было что-то симулятивное: у меня есть изображение атрибута в моей модели, это содержит расположение файла в папке 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); } 

в моем случае, создав пустой столбец и установив, что его аксессуар работал нормально. мой аксессуар заполняет возраст пользователя из столбца dob. toArray () тоже работает.

 public function getAgeAttribute() { return Carbon::createFromFormat('Ym-d', $this->attributes['dateofbirth'])->age; } 

В моей модели подписки мне нужно знать, что подписка приостановлена ​​или нет. вот как я сделал это public function getIsPausedAttribute() { $isPaused = false; if (!$this->is_active) { $isPaused = true; } } public function getIsPausedAttribute() { $isPaused = false; if (!$this->is_active) { $isPaused = true; } }

то в шаблоне представления я могу использовать $subscription->is_paused для получения результата.

getIsPausedAttribute – это формат для установки пользовательского атрибута,

и использует is_paused для получения или использования атрибута в вашем представлении.