2016-01-20 8 views
13

यह सुविधाजनक है कि लार्वेल मॉडल एक विधि प्रदान करता है कि यह किसी अन्य संबंधित तालिका से परिणाम वापस कर सकता है।क्यों लार्वा मॉडल डेटा का सेट डुप्लिकेट करता है और कैसे (यदि संभव हो) डेटा का केवल एक सेट है?

उदाहरण के लिए, मैं एक मेज बुलाया आइटम और प्रतिक्रिया नामक एक और मेज, जहां आइटम तालिका में आइटम की प्रतिक्रिया तालिका भंडार प्रतिक्रिया। तो, आईडी के साथ 1 आइटम के सभी प्रतिक्रिया प्राप्त करने, मुझे क्या करना होगा:

Item::find(1)->feedback; 

और निम्नलिखित इस वस्तु का प्रिंटआउट लौट आए।

Illuminate\Database\Eloquent\Collection Object 
( [items:protected] => Array 
     (
      [0] => Feedback Object 
       (
        [table:protected] => feedback 
        [connection:protected] => 
        [primaryKey:protected] => id 
        [perPage:protected] => 15 
        [incrementing] => 1 
        [timestamps] => 1 
        [attributes:protected] => Array 
         (
          [id] => 1 
          [rma_id] => 3 
          [item_id] => 8 
          [quo_id] => 0 
          [case_id] => i2eM20160120 
          [line_no] => 000001 
          [content] => test 
          [status] => sent 
          [read] => 0 
          [sender] => Tester 
          [created_at] => 2016-01-20 18:03:44 
          [updated_at] => 2016-01-20 18:03:44 
         ) 

        [original:protected] => Array 
         (
          [id] => 1 
          [rma_id] => 3 
          [item_id] => 8 
          [quo_id] => 0 
          [case_id] => i2eM20160120 
          [line_no] => 000001 
          [content] => test 
          [status] => sent 
          [read] => 0 
          [sender] => Tester 
          [created_at] => 2016-01-20 18:03:44 
          [updated_at] => 2016-01-20 18:03:44 
         ) 

        [relations:protected] => Array 
         (
         ) 

        [hidden:protected] => Array 
         (
         ) 

        [visible:protected] => Array 
         (
         ) 

        [appends:protected] => Array 
         (
         ) 

        [fillable:protected] => Array 
         (
         ) 

        [guarded:protected] => Array 
         (
          [0] => * 
         ) 

        [dates:protected] => Array 
         (
         ) 

        [touches:protected] => Array 
         (
         ) 

        [observables:protected] => Array 
         (
         ) 

        [with:protected] => Array 
         (
         ) 

        [morphClass:protected] => 
        [exists] => 1 
       ) 

     ) 

) 

यह ठीक काम करता है, और यह पता चलता आईडी 1.

साथ आइटम पर केवल एक ही प्रतिक्रिया क्या चिंताओं मुझे उस डाटासेट [attributes:protected] और [original:protected] में दोहराया गया है है नहीं है। यह सिर्फ एक परीक्षण मामला है और वास्तविक मामले में हजारों फीडबैक होंगे और एक डुप्लिकेट डेटासेट होने से स्मृति का एक बड़ा अपशिष्ट होगा। यदि मैं DB::table('table_name') दृष्टिकोण का उपयोग कर रहा हूं, तो डेटासेट डुप्लिकेट नहीं किया गया है, लेकिन यह बहुत कम सुविधाजनक है।

क्यों laravel मॉडल में डेटा नकल करने की जरूरत है?

और वहाँ यह डेटा का केवल एक सेट वापसी बनाने के लिए एक तरीका है?

वर्तमान में मैं क्वेरी के बाद अनावश्यक डेटा को कम करने के लिए ->toArray() का उपयोग कर रहा हूं, लेकिन स्मृति उपयोग अभी भी वहां है क्योंकि लार्वेल अभी भी डेटा का सेट बना रहा है।

+0

तकनीकी तौर पर आप जिस तरह से सुवक्ता तो वस्तुओं उत्पन्न करता है पसंद नहीं है:

कृपया विवरण के लिए इस लिंक को देख। एक ओआरएम का उपयोग करें जो आप करते हैं या अपना कोड लिखते हैं और फिर वालोकेंट अक्षम करते हैं। – Pitchinnate

+0

ओआरएम के लिए कोई सुझाव? @ पिचिनेट – cytsunny

+0

निश्चित नहीं है, आपको अलग-अलग ओआरएम द्वारा लौटाए गए सभी अलग-अलग ढांचे को देखना होगा जो आपको पसंद है और ऐसा लगता है कि स्मृति बर्बाद नहीं कर रहा है। सबसे बड़ा PHP आधारित ओआरएम जिसे मैं जानता हूं वह सिद्धांत है। – Pitchinnate

उत्तर

4

हालांकि यह एक अच्छा उदाहरण पाने के लिए मुश्किल है, यह आप निश्चित रूप से सहेजने से पहले विशेषता सेट करने की अनुमति देता है। शायद यदि आप कई कार्यों के माध्यम से जाते हैं और आखिरकार जांच करते हैं कि अंतिम चर के लिए सबकुछ सही ढंग से सेट किया गया है, तो अलग-अलग चरों में सबकुछ स्टोर करने की आवश्यकता के बिना।

बहुत छोटा सा उदाहरण:

$user = User::find(1); 
print_r($user); 
$user->name = 'John Doe'; 
print_r($user); 
$user->save(); 
print_r($user()); 

रिटर्न कुछ की तरह:

पहले प्रिंट:

[attributes:protected] => Array 
(
    [id] => 1 
    [name] => 'Jimmy Doe' 
    ... 
) 
[original:protected] => Array 
(
    [id] => 1 
    [name] => 'Jimmy Doe' 
    ... 
) 

दूसरा प्रिंट:

[attributes:protected] => Array 
(
    [id] => 1 
    [name] => 'John Doe' 
    ... 
) 
[original:protected] => Array 
(
    [id] => 1 
    [name] => 'Jimmy Doe' 
    ... 
) 

तीसरे प्रिंट:

[attributes:protected] => Array 
(
    [id] => 1 
    [name] => 'John Doe' 
    ... 
) 
[original:protected] => Array 
(
    [id] => 1 
    [name] => 'John Doe' 
    ... 
) 

के बाद ही बचाने() डेटा वास्तव में डीबी में सहेजा जा रहा है।

सुवक्ता के syncOriginal() ऊपर निकाल दिया जाता है जब एक मॉडल को बचाने() 'घ है:

/** 
* Sync the original attributes with the current. 
* 
* @return $this 
*/ 
public function syncOriginal() 
{ 
    $this->original = $this->attributes; 

    return $this; 
} 
+0

अब मैं समझता हूं कि यह इस तरह से क्यों सेट है, लेकिन क्या यह सुविधा अक्षम करना संभव है? (यानी सामान्य ऑब्जेक्ट की तरह व्यवहार करता है, पिछले मान को सहेजने की आवश्यकता नहीं है, केवल save() फ़ंक्शन का उपयोग करते समय डेटाबेस में सहेजता है) – cytsunny

+0

lib के अनुसार, इसे अक्षम करने के लिए कोई फ़ंक्शन नहीं है। लेकिन प्रदर्शन के लिए, आप केवल आवश्यक कुंजी प्राप्त करके आवश्यक कुंजी की संख्या सीमित कर सकते हैं, जैसे '' 'उपयोगकर्ता उपयोगकर्ता = उपयोगकर्ता :: जहां ('नाम', 'जॉन डो') -> प्राप्त करें ('ईमेल');' 'यह सरणी के आकार को कम करेगा। एक और विकल्प एलोक्वेंट का उपयोग @ पिचिनेट के रूप में नहीं करना है। – Th3Alchemist

+0

ओआरएम के लिए कोई सुझाव जो मैंने उल्लेख किया है? – cytsunny

3

मूल डेटा आदेश मॉडल गंदा जाँच प्रदर्शन करने के लिए अनुमति देने के लिए में संग्रहित है। डेटाबेस अद्यतनों को संभालने के लिए आंतरिक रूप से गंदा जांच का उपयोग किया जाता है।

एक मॉडल गंदा नहीं है और आप इसे बचाने की कोशिश करते हैं, तो कोई अद्यतन प्रदर्शन किया जाएगा।यदि कोई मॉडल गंदा है और आप इसे सहेजने का प्रयास करते हैं, तो केवल उन फ़ील्ड को गंदा किया जाएगा।

तुम सच में चाहता था यदि यह से छुटकारा पाने के लिए, आप मॉडल पर syncOriginal() और syncOriginalAttribute() तरीकों रद्द कर सकते थे। यदि आपने ऐसा किया है, तो इसका मतलब यह होगा कि मॉडल हमेशा गंदा माना जाएगा। getDirty() हमेशा सभी विशेषताओं को वापस कर देगा, और isDirty() हमेशा true लौटाएगा।

आप टाइम स्टांप का उपयोग करते हैं, आप भी updateTimestamps() विधि ओवरराइड करने के लिए, अन्यथा आपके updated_at और created_at क्षेत्रों कभी नहीं तैयार हो जाओ होगा की आवश्यकता होगी।

class Feedback extends Model 
{ 
    // ... 

    public function syncOriginal() 
    { 
     return $this; 
    } 

    public function syncOriginalAttribute($attribute) 
    { 
     return $this; 
    } 

    protected function updateTimestamps() 
    { 
     $time = $this->freshTimestamp(); 

     $this->setUpdatedAt($time); 

     if (! $this->exists) { 
      $this->setCreatedAt($time); 
     } 
    } 

    // ... 
} 

अन्य प्रतिक्रियाएं हो सकती हैं जो कोड की समीक्षा करते समय तुरंत दिखाई नहीं दे रही हैं।

यह सब कहकर, अगर आपको स्मृति के बारे में यह चिंता हो रही है, तो आपको अपने दृष्टिकोण और आप जो करने की कोशिश कर रहे हैं, उसके बारे में दूसरा विचार करने की आवश्यकता हो सकती है। क्या आपको वास्तव में एक बार में सभी प्रतिक्रियाओं को लोड करने की आवश्यकता है? क्या यह एक ऑपरेशन है जो chunk एड हो सकता है? क्या यह काम कतार में व्यक्तिगत नौकरियों द्वारा बेहतर ढंग से किया जाएगा? आदि ...

3

यह कोई मुद्दा नहीं होना चाहिए यह सोचकर कि PHP आंतरिक रूप से कैसे काम करता है। जब तक 'गुण' संशोधित नहीं होते हैं, 'गुण' केवल 'मूल' (या दूसरी तरफ) के लिए एक सूचक होता है, इसलिए दोनों सरणीएं लगभग एक ही मात्रा में स्मृति लेती हैं क्योंकि उनमें से केवल एक ही है। यही कारण है कि जब आप toArray() करते हैं तो स्मृति उपयोग नहीं बदलता है। आप यह सिर्फ है क्या में बनाया गया है Laravel के साथ अपने ORM के रूप में सुवक्ता उपयोग करने के लिए की जरूरत नहीं है http://blog.ircmaxell.com/2014/12/what-about-garbage.html

संबंधित मुद्दे