Dodać własny atrybut do modelu Laravel / Eloquent przy ładowaniu?

Chciałbym móc dodać niestandardowy atrybut / właściwość do modelu Laravel / Eloquent po załadowaniu, podobny do tego, jak można to osiągnąć z RedBean ' s $model->open() Metoda.

Na przykład w tej chwili w moim kontrolerze mam:

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

Byłoby miło móc pominąć pętlę i mieć atrybut' available ' już ustawiony i wypełniony.

Próbowałem użyć niektórych zdarzeń modelu opisanych w dokumentacji, aby załączyć to właściwość, gdy obiekt ładuje się, ale do tej pory bez powodzenia.

uwagi:

  • "dostępny" nie jest polem w tabeli bazowej.
  • $sessions jest zwracany jako obiekt JSON jako część API, a zatem wywołanie czegoś takiego jak $session->available() w szablonie nie jest opcją
Author: Kirk Beard, 2013-06-21

9 answers

Problem jest spowodowany faktem, że metoda Model S toArray() ignoruje wszelkie Accesory, które nie odnoszą się bezpośrednio do kolumny w tabeli bazowej.

Jak wspomniał Taylor Otwell tutaj, "jest to celowe i ze względów wydajnościowych."Jednak jest łatwy sposób, aby to osiągnąć:

class EventSession extends Eloquent {

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

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

Wszelkie atrybuty wymienione we właściwości $ appends zostaną automatycznie dołączone do tablicy lub postaci JSON modelu, pod warunkiem, że dodałeś odpowiednie / align = "left" /

Stara odpowiedź (dla wersji Laravel

Najlepszym rozwiązaniem, jakie znalazłem, jest nadpisanie metody toArray() i albo explicity ustaw atrybut:

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

}
Jeśli masz wiele niestandardowych akcesoriów, przejrzyj je wszystkie i zastosuj:]}
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);    
    }

}
 343
Author: coatesap,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-03 13:59:45

Ostatnia rzecz na stronie Laravel Eloquent doc to:

protected $appends = array('is_admin');

, które mogą być używane automatycznie do dodawania nowych accesorów do modelu bez żadnych dodatkowych prac, takich jak modyfikowanie metod, takich jak ::toArray().

Po prostu utwórz getFooBarAttribute(...) accessor i dodaj foo_bar do $appends tablicy.

 124
Author: trm42,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 06:01:30

Jeśli zmienisz nazwę swojej metody getAvailability() na getAvailableAttribute() twoja metoda stanie się accessorem i będziesz mógł ją odczytać używając ->available bezpośrednio na twoim modelu.

Docs: https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators

EDIT: ponieważ twój atrybut jest "wirtualny", nie jest on domyślnie uwzględniany w reprezentacji JSON Twojego obiektu.

Ale znalazłem to: Custom model accessors Nie przetwarzane, gdy ->tojson() wywołane?

In aby wymusić zwrócenie atrybutu w tablicy, dodaj go jako klucz do tablicy $ attributes.

class User extends Eloquent {
    protected $attributes = array(
        'ZipCode' => '',
    );

    public function getZipCodeAttribute()
    {
        return ....
    }
}

Nie testowałem go, ale powinno być dość trywialne dla ciebie, aby spróbować w obecnej konfiguracji.

 40
Author: Alexandre Danault,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-16 20:21:24

Miałem coś symulowanego: Mam obraz atrybutu w moim modelu, który zawiera lokalizację pliku w folderze przechowywania. Obraz musi być zwrócony Base64 zakodowany

//Add extra attribute
protected $attributes = ['picture_data'];

//Make it available in the json response
protected $appends = ['picture_data'];

//implement the attribute
public function getPictureDataAttribute()
{
    $file = Storage::get($this->picture);
    $type = Storage::mimeType($this->picture);
    return "data:" . $type . ";base64," . base64_encode($file);
}
 25
Author: Patrique,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-05 11:13:40

Możesz użyć funkcji setAttribute w modelu, aby dodać własny atrybut

 18
Author: jianfeng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-28 07:59:08

Krok 1: Zdefiniuj atrybuty w $appends
Krok 2: Zdefiniuj accessor dla tych atrybutów.
Przykład:

<?php
...

class Movie extends Model{

    protected $appends = ['cover'];

    //define accessor
    public function getCoverAttribute()
    {
        return json_decode($this->InJson)->cover;
    }

 17
Author: Bedram Tamang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-27 03:35:16

Powiedzmy, że masz 2 kolumny o nazwach first_name i last_name w tabeli users i chcesz odzyskać pełną nazwę. możesz osiągnąć za pomocą następującego kodu:

class User extends Eloquent {


    public function getFullNameAttribute()
    {
        return $this->first_name.' '.$this->last_name;
    }
}

Teraz możesz uzyskać pełną nazwę jako:

$user = User::find(1);
$user->full_name;
 9
Author: ShuBham GuPta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-23 12:26:25

W moim modelu subskrypcji, muszę wiedzieć, że subskrypcja jest wstrzymana lub nie. oto jak to zrobiłem

public function getIsPausedAttribute() {
    $isPaused = false;
    if (!$this->is_active) {
        $isPaused = true;
    }
}

Wtedy w szablonie widoku mogę użyć $subscription->is_paused Aby uzyskać wynik.

{[2] } jest formatem do ustawiania niestandardowego atrybutu,

I używa is_paused, aby uzyskać lub użyć atrybutu w widoku.

 3
Author: li bing zhao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-21 23:46:23

W moim przypadku tworzenie pustej kolumny i ustawianie jej accesora działało dobrze. mój accessor wypełniający wiek użytkownika z kolumny dob. funkcja toArray() również działała.

public function getAgeAttribute()
{
  return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}
 2
Author: Hanif Rifa'i,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-31 21:53:11