लोड पर एक लारावेल / एलोकेंट मॉडल के लिए एक कस्टम विशेषता जोड़ें?


219

मैं एक कस्टम विशेषता / संपत्ति को एक लारावेल / एलोक्वेंट मॉडल में जोड़ने में सक्षम होना चाहता हूं जब इसे लोड किया जाता है, तो RedBean की $model->open() विधि के साथ इसे कैसे प्राप्त किया जा सकता है ।

उदाहरण के लिए, इस समय, मेरे नियंत्रक में:

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

लूप को छोड़ना अच्छा होगा और पहले से सेट और पॉपुलेटेड 'उपलब्ध' विशेषता के लिए अच्छा होगा।

मैंने दस्तावेज़ीकरण में वर्णित कुछ मॉडल घटनाओं का उपयोग करके इस संपत्ति को संलग्न करने की कोशिश की है जब ऑब्जेक्ट लोड होता है, लेकिन अब तक सफलता के बिना।

टिप्पणियाँ:

  • 'उपलब्ध' अंतर्निहित तालिका में फ़ील्ड नहीं है।
  • $sessionsएक एपीआई के हिस्से के रूप में JSON ऑब्जेक्ट के रूप में लौटाया जा रहा है, और इसलिए $session->available()टेम्पलेट में कुछ कॉल करना एक विकल्प नहीं है

जवाबों:


317

समस्या तथ्य यह है कि के कारण होता है Modelकी toArray()विधि किसी भी accessors जो सीधे अंतर्निहित तालिका में किसी स्तंभ से संबंधित नहीं ध्यान नहीं देता।

जैसा कि टेलर ओटवेल ने यहां उल्लेख किया है , "यह जानबूझकर और प्रदर्शन कारणों से है।" हालाँकि इसे प्राप्त करने का एक आसान तरीका है:

class EventSession extends Eloquent {

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

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

$ अपेंडेंस प्रॉपर्टी में सूचीबद्ध कोई भी विशेषता स्वचालित रूप से मॉडल के ऐरन या JSON फॉर्म में शामिल होगी, बशर्ते कि आपने उपयुक्त एक्सेसर जोड़ा हो।

पुराना उत्तर (लारवेल संस्करणों के लिए <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);    
    }

}

आज के लिए सबसे अच्छा सवाल और जवाब। मैं इसे प्राप्त करने के तरीके पर अलग-अलग कार्यान्वयन पर काम कर रहा था और लारवेल पर एक प्रश्न पोस्ट करने से पहले। मुझे यह मिला! वाह !!!
गयान हेवा

और वहाँ सिर्फ कुछ मामलों के लिए उन्हें जोड़ने के लिए नहीं करने के लिए एक रास्ता है?
जोर्डी पुइग्डेलविल

3
रिलेशनशिप के माध्यम से मॉडल को कॉल करते समय ये रीति-रिवाज़ विशेषताएँ दिखाई नहीं देती हैं। (पूर्व: मॉडल \ कंपनी :: ('लोगों') के साथ)। कोई उपाय?
एंड्रयू

@ JordiPuigdellívol Laravel 5 में, आप protected $hidden = []कॉलम / एक्सेसर्स को बाहर निकालने के लिए जोड़ सकते हैं ।
जंकटिसु

124

Laravel सुवक्ता दस्तावेज़ पृष्ठ पर आखिरी बात है:

protected $appends = array('is_admin');

इसका उपयोग बिना किसी अतिरिक्त कार्य जैसे संशोधन के तरीकों के बिना मॉडल में नए एक्सेसर्स को जोड़ने के लिए स्वचालित रूप से किया जा सकता है ::toArray()

बस बनाने के getFooBarAttribute(...)एक्सेसर और जोड़ने foo_barके लिए $appendsसरणी।


4
आह दिलचस्प है। मेरा प्रश्न पोस्ट किए जाने के बाद से यह सुविधा लारवेल में जोड़ दी गई है ( github.com/laravel/framework/commit/… )। यह v4.08 या उच्चतर का उपयोग करने वाले किसी भी व्यक्ति के लिए सही उत्तर है।
coatesap

3
यदि आप अपने एक्सेसरों के लिए सामग्री बनाने के लिए रिश्तों का उपयोग कर रहे हैं तो यह आपके लिए उपलब्ध नहीं होगा। इस उदाहरण में, आपको toArrayविधि को ओवरराइड करने का सहारा लेना पड़ सकता है ।
gpmcadam

2
ऐसा लगता है कि आपके द्वारा संदर्भित दस्तावेज़ यहाँ ले जाया गया है: https://laravel.com/docs/5.5/eloquent-serialization
मब्बलर

40

आप अपने नाम बदलते हैं getAvailability()विधि के लिए getAvailableAttribute()अपनी पद्धति एक हो जाता है एक्सेसर और आप का उपयोग कर इसे पढ़ने के लिए सक्षम हो जाएगा ->availableसीधे अपने मॉडल पर।

डॉक्स: https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators

संपादित करें: चूंकि आपकी विशेषता "आभासी" है, इसलिए यह आपकी वस्तु के JSON प्रतिनिधित्व में डिफ़ॉल्ट रूप से शामिल नहीं है।

लेकिन मुझे यह पता चला: कस्टम मॉडल एक्सेसरों को संसाधित नहीं किया गया -> toJson () कहा जाता है?

अपनी विशेषता को सरणी में वापस लाने के लिए मजबूर करने के लिए, इसे $ विशेषता सरणी की कुंजी के रूप में जोड़ें।

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

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

मैंने इसका परीक्षण नहीं किया, लेकिन आपको अपने वर्तमान सेटअप में प्रयास करने के लिए बहुत तुच्छ होना चाहिए।


यह उतना ही काम करता है जितना कि यह वस्तु ->availableपर उपलब्ध होता है $session, लेकिन जैसा कि $sessionsसीधे JSON स्ट्रिंग में परिवर्तित हो जाता है (यह एक एपीआई का हिस्सा है), इसका उपयोग करने का कोई मौका नहीं है।
coatesap

मुझे यकीन नहीं है कि मैं समझता हूं कि आपका सामान कैसे काम करता है। यदि EventSession::all()एक एपीआई से JSON ऑब्जेक्ट लौटाता है, तो आप वास्तव में एक लारवेल मॉडल का उपयोग नहीं कर रहे हैं, है ना? क्षमा करें, मैं भ्रमित हूं कि आपने कैसे मॉडल लागू किया।
एलेक्जेंड्रे डानॉल्ट

EventSession एक मानक वाक्पटु वस्तु ( class EventSession extends Eloquent) है। ::all()एक उदाहरण के रूप में है। EventSession::find(170071)एक और होगा। इन्हें SessionController ( SessionController extends \BaseController) में विभिन्न बिंदुओं पर बुलाया जाता है, जिन्हें '/ सत्र / 170071' जैसे URL के माध्यम से बुलाया जाएगा।
coatesap

मुझे लगता है कि Jlo रूपांतरण के लिए एलोकेंट की अंतर्निहित वस्तु में कुंजी निहित हो सकती है। यहां तक ​​कि अगर आप एक कस्टम विशेषता जैसे public $availableकि मॉडल में जोड़ते हैं , तो यह तब नहीं दिखाया जाता है जब ऑब्जेक्ट परिवर्तित हो जाता है।
coatesap

3
यह 8 अक्टूबर, 2013 को लारवेल 4.0.8 की रिलीज़ के बाद से उपलब्ध है। आधिकारिक डॉक्स देखें: laravel.com/docs/eloquent#converting-to-arrays-or-json (इसके लिए देखें protected $appends = array('is_admin');)
रोनाल्ड

23

मेरे पास कुछ सिमुलर था: मेरे मॉडल में एक विशेषता चित्र है, इसमें स्टोरेज फ़ोल्डर में फ़ाइल का स्थान है। छवि को बेस 64 एनकोडेड लौटाया जाना चाहिए

//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
यह $ विशेषताओं और $ append में चित्र नहीं होना चाहिए। और आप $ गुण चर को भी छोड़ सकते हैं।
मदुशन परेरा

16

आप setAttributeएक कस्टम विशेषता जोड़ने के लिए मॉडल में फ़ंक्शन का उपयोग कर सकते हैं


9

मान लें कि आपके उपयोगकर्ता तालिका में पहले_नाम और last_name नाम के 2 कॉलम हैं और आप पूरा नाम पुनः प्राप्त करना चाहते हैं। आप निम्नलिखित कोड के साथ प्राप्त कर सकते हैं:

class User extends Eloquent {


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

अब आप पूरा नाम इस प्रकार ले सकते हैं:

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

7

चरण 1: $appends
चरण 2 में विशेषताओं को परिभाषित करें: उस विशेषताओं के लिए सहायक उपकरण को परिभाषित करें।
उदाहरण:

<?php
...

class Movie extends Model{

    protected $appends = ['cover'];

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

3

मेरे सदस्यता मॉडल में, मुझे यह जानना होगा कि सदस्यता रोक दी गई है या नहीं। यहाँ देखें कि मैंने यह कैसे किया

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

फिर दृश्य टेम्पलेट में, मैं $subscription->is_pausedपरिणाम प्राप्त करने के लिए उपयोग कर सकता हूं ।

getIsPausedAttributeकस्टम विशेषता सेट करने के लिए प्रारूप है,

और is_pausedआपके विचार में विशेषता को प्राप्त करने या उपयोग करने के लिए उपयोग करता है।


2

मेरे मामले में, एक खाली कॉलम बनाने और उसके एक्सेसर को ठीक करने के लिए काम किया। मेरा अभिगमनकर्ता dob कॉलम से उपयोगकर्ता की आयु भर रहा है। .Array () फ़ंक्शन ने भी काम किया।

public function getAgeAttribute()
{
  return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.