it-swarm.com.de

Hinzufügen eines benutzerdefinierten Attributs zu einem Laravel/Eloquent-Modell beim Laden?

Ich möchte gerne ein benutzerdefiniertes Attribut/eine benutzerdefinierte Eigenschaft zu einem Laravel/Eloquent-Modell hinzufügen, wenn es geladen wird, ähnlich wie dies mit der Methode RedBean$model->open() möglich ist.

Im Moment habe ich zum Beispiel in meinem Controller:

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

Es wäre schön, die Schleife weglassen zu können und das Attribut 'available' bereits gesetzt und gefüllt zu haben.

Ich habe versucht, einige der in der Dokumentation beschriebenen Modellereignisse zu verwenden, um diese Eigenschaft beim Laden des Objekts anzuhängen, jedoch bisher ohne Erfolg.

Anmerkungen:

  • 'available' ist kein Feld in der zugrundeliegenden Tabelle.
  • $sessions wird als JSON-Objekt als Teil einer API zurückgegeben. Daher ist das Aufrufen von etwas wie $session->available() in einer Vorlage keine Option
168
coatesap

Das Problem wird durch die Tatsache verursacht, dass die toArray()-Methode der Variable Model Accessoren ignoriert, die sich nicht direkt auf eine Spalte in der zugrunde liegenden Tabelle beziehen.

Wie Taylor Otwell hier erwähnte: "Dies ist aus Gründen der Leistung beabsichtigt." Es gibt jedoch einen einfachen Weg, dies zu erreichen:

class EventSession extends Eloquent {

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

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

Alle in der $ appends-Eigenschaft aufgelisteten Attribute werden automatisch in das Array- oder JSON-Formular des Modells aufgenommen, sofern Sie den entsprechenden Zugriffsmechanismus hinzugefügt haben.

Alte Antwort (für Laravel-Versionen <4.08):

Die beste Lösung, die ich gefunden habe, ist, die toArray()-Methode zu überschreiben und entweder das Attribut explicity festzulegen:

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

}

oder, wenn Sie über viele benutzerdefinierte Zugriffsmethoden verfügen, führen Sie eine Schleife durch und wenden Sie sie an:

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

}
273
coatesap

Das letzte - was auf der Laravel Eloquent-Dokumentseite ist:

protected $appends = array('is_admin');

Dies kann automatisch verwendet werden, um neue Zugriffsmethoden zum Modell hinzuzufügen, ohne dass zusätzliche Arbeiten wie das Ändern von Methoden wie ::toArray() erforderlich sind. 

Erstellen Sie einfach getFooBarAttribute(...) accessor und fügen Sie das foo_bar zu $appends hinzu. 

107
trm42

Wenn Sie Ihre getAvailability()-Methode in getAvailableAttribute() umbenennen, wird Ihre Methode zu accessor und Sie können sie mit ->available direkt in Ihrem Modell lesen.

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

BEARBEITEN: Da Ihr Attribut "virtuell" ist, ist es standardmäßig nicht in der JSON-Darstellung Ihres Objekts enthalten.

Aber ich habe folgendes gefunden: Benutzerdefinierte Zugriffsmuster werden nicht verarbeitet, wenn -> toJson () aufgerufen wird?

Um zu erzwingen, dass Ihr Attribut im Array zurückgegeben wird, fügen Sie es dem Array $ attributes als Schlüssel hinzu.

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

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

Ich habe es nicht getestet, sollte aber ziemlich trivial sein, um es in Ihrem aktuellen Setup auszuprobieren.

32

Ich hatte etwas ähnliches: Ich habe ein Attributbild in meinem Modell. Dieses enthält den Speicherort der Datei im Speicherordner . Das Bild muss base64-codiert zurückgegeben werden

//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);
}
12
Patrique

sie können die Funktion setAttribute in Model verwenden, um ein benutzerdefiniertes Attribut hinzuzufügen

12
jianfeng

Angenommen, Sie haben 2 Spalten mit dem Namen first_name und last_name in Ihrer Benutzertabelle, und Sie möchten den vollständigen Namen abrufen. Sie können mit dem folgenden Code erreichen:

class User extends Eloquent {


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

jetzt können Sie vollen Namen erhalten als:

$user = User::find(1);
$user->full_name;
2
ShuBham GuPta

in meinem Fall funktionierte das Erstellen einer leeren Spalte und das Festlegen des Zugriffsmoduls einwandfrei. toArray () funktionierte auch.

public function getAgeAttribute()
{
  return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}
1
Hanif Rifa'i

In meinem Abonnementmodell muss ich wissen, dass das Abonnement angehalten ist oder nicht . So habe ich es gemacht public function getIsPausedAttribute() { $isPaused = false; if (!$this->is_active) { $isPaused = true; } }

in der Ansichtsvorlage kann ich dann mit $subscription->is_paused das Ergebnis erhalten. 

Die Variable getIsPausedAttribute ist das Format, um ein benutzerdefiniertes Attribut festzulegen.

und verwendet is_paused, um das Attribut in Ihrer Ansicht abzurufen oder zu verwenden. 

0
li bing zhao