Я бы хотел добавить пользовательский атрибут / свойство в модель 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
для получения или использования атрибута в вашем представлении.