Yüklü bir Laravel / Eloquent modeline özel bir özellik eklensin mi?


219

Bir Laravel / Eloquent modeline yüklendiğinde RedBean'ın $model->open() yöntemiyle nasıl elde edilebileceğine benzer şekilde özel bir özellik / özellik ekleyebilmek istiyorum .

Örneğin, şu anda, kontrol cihazımda:

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

Döngüyü atlamak ve önceden ayarlanmış ve doldurulmuş 'kullanılabilir' özniteliğe sahip olmak güzel olurdu.

Nesne yüklendiğinde, ancak şimdiye kadar başarı olmadan bu özelliği eklemek için belgelerde açıklanan bazı model olayları kullanarak denedim.

Notlar:

  • 'kullanılabilir' temel tablodaki bir alan değildir.
  • $sessionsAPI'nin bir parçası olarak JSON nesnesi olarak döndürülüyor ve bu nedenle $session->available()şablonda olduğu gibi bir şey çağırmak bir seçenek değil

Yanıtlar:


318

Sorunun nedeni, Model' toArray()yönteminin temel tablodaki bir sütunla doğrudan ilişkili olmayan erişimcileri yok saymasıdır.

Taylor Otwell'in burada belirttiği gibi , "Bu kasıtlı ve performans nedenleriyle." Bununla birlikte, bunu başarmanın kolay bir yolu vardır:

class EventSession extends Eloquent {

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

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

$ Appends özelliğinde listelenen tüm özellikler, uygun erişimciyi eklemiş olmanız koşuluyla modelin dizisine veya JSON formuna otomatik olarak dahil edilir.

Eski yanıt (Laravel <4.08 sürümleri için):

Bulduğum en iyi çözüm toArray()yöntemi geçersiz kılmak ve ya özniteliği özniteliği ayarlamaktır:

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

}

veya çok sayıda özel erişimciniz varsa hepsini gözden geçirin ve uygulayın:

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

}

Bugün için en iyi soru ve cevap. Bunu başarmak için farklı uygulamalar üzerinde çalışıyordum ve laravel.io'ya bir soru göndermeden önce bunu buldum! Yaşasın !!!
Gayan Hewa

Ve sadece bazı durumlarda json'a eklememenin bir yolu var mı?
Jordi Puigdellívol

3
Bu gümrük özellikleri, modeli bir ilişki yoluyla çağırırken görünmüyor. (Örn: Modeller \ Şirket :: ile ('kişi')). Herhangi bir fikir?
Andrew

@ JordiPuigdellívol Laravel 5'te, dışlanacak protected $hidden = []sütunları / erişimcileri eklemek için kullanabilirsiniz.
junkystu

124

Laravel Eloquent doc sayfasından son şey geçerli:

protected $appends = array('is_admin');

Bu, modifikasyon yöntemleri gibi herhangi bir ek çalışma olmadan modele yeni erişimciler eklemek için otomatik olarak kullanılabilir ::toArray().

Sadece oluşturmak getFooBarAttribute(...)erişimci ve eklemek foo_bariçin $appendsdiziden.


4
Ah ilginç. Bu özellik, sorum gönderildiğinden Laravel'e eklendi ( github.com/laravel/framework/commit/… ). Bu v4.08 veya üstü kullanan herkes için doğru cevaptır.
coatesap

3
Erişimcileriniz için içerik oluşturmak amacıyla ilişkiler kullanıyorsanız, bu özellik size ulaşmayacaktır. Bu durumda, geçersiz kılmaya başvurmanız gerekebilirtoArray yöntemi .
gpmcadam

2
Anlattığınız belgeler buraya taşınmış gibi görünüyor: https://laravel.com/docs/5.5/eloquent-serialization .
mibbler

40

getAvailability()Yönteminizi yönteminize yeniden adlandırırsanız erişimcigetAvailableAttribute() olur ve doğrudan modelinizi kullanarak okuyabilirsiniz .->available

Dokümanlar: https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators

DÜZENLE: Özniteliğiniz "sanal" olduğundan, varsayılan olarak nesnenizin JSON temsiline dahil edilmez.

Ama buldum: Özel model erişimciler -> toJson () çağrıldığında işlenmedi?

Özniteliğinizi dizide döndürülmeye zorlamak için, $ attributes dizisine bir anahtar olarak ekleyin.

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

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

Test etmedim, ancak mevcut kurulumunuzda denemeniz için oldukça önemsiz olmalı.


Bu ->available, $sessionnesne üzerinde kullanılabilir olduğu gibi çalışır , ancak $sessionsdoğrudan bir JSON dizesine (API'nın bir parçası) dönüştürüldüğünde, bunu kullanma şansı yoktur.
coatesap

Eşyalarınızın nasıl çalıştığını anladığımdan emin değilim. Eğer EventSession::all()bir API gelen getiriler bir JSON nesnesi, gerçekten, hakkını bir laravel modeli kullanmıyorsunuz? Üzgünüm, modelinizi nasıl uyguladığınız konusunda kafam karıştı.
Alexandre Danault

EventSession standart bir Eloquent nesnesidir ( class EventSession extends Eloquent). ::all()örnek olarak verilebilir. EventSession::find(170071)başka olurdu. Bunlar, SessionController extends \BaseController'/ sessions / 170071' gibi URL'ler aracılığıyla çağrılacak olan SessionController ( ) boyunca çeşitli noktalarda çağrılır.
coatesap

Ben anahtar Eloquent's yerleşik nesnede gerçekleşen JSON dönüşüm yalan düşünüyorum. public $availableModele gibi özel bir öznitelik ekleseniz bile, nesne dönüştürüldüğünde bu gösterilmez.
coatesap

3
Bu, Laravel 4.0.8'in 8 Ekim 2013'te yayınlanmasından bu yana kullanılabilir. Resmi dokümanlara bakın: laravel.com/docs/eloquent#converting-to-arrays-or-json (ara protected $appends = array('is_admin');)
Ronald Hulshof

23

Ben simüler bir şey vardı: Modelimde bir öznitelik resmi var, bu Depolama klasöründeki dosyanın konumunu içerir. Görüntü, base64 kodlu olarak döndürülmelidir

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

1
$ Attributes & $ appends içindeki pictureData değil picture_data olmalıdır. Ve $ attributes değişkenini de atlayabilirsiniz.
Madushan Perera

16

setAttributeözel bir özellik eklemek için Model'deki işlevi kullanabilirsiniz


9

Kullanıcılar tablonuzda first_name ve last_name adlı 2 sütununuz olduğunu ve tam adı almak istediğinizi varsayalım. aşağıdaki kod ile elde edebilirsiniz:

class User extends Eloquent {


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

şimdi tam adı alabilirsiniz:

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

7

Adım 1: $appends
Adım 2'de öznitelikleri tanımlayın: Öznitelikler için erişimci tanımlayın.
Misal:

<?php
...

class Movie extends Model{

    protected $appends = ['cover'];

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

3

Abonelik modelimde aboneliğin duraklatılmış olup olmadığını bilmem gerekiyor. işte böyle yaptım

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

sonra görünüm şablonunda, $subscription->is_paused sonucu elde etmek için .

getIsPausedAttributeÖzel bir özellik ayarlamak için biçimidir,

ve is_pausedözelliği görünümünüzde almak veya kullanmak için kullanır .


2

benim durumumda, boş bir sütun oluşturmak ve erişimcisi ayarlamak iyi çalıştı. erişimcim dob sütunundan kullanıcının yaşını dolduruyor. toArray () işlevi de çalıştı.

public function getAgeAttribute()
{
  return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.