2014-04-08 7 views
6

लार्वेल 4 प्रोजेक्ट, एलोक्वेंट ओआरएम का उपयोग करके पुनर्प्राप्त करें।लैरवेल: कई से कई लोगों को, अलग-अलग() मान

मेरे पास तीन टेबल हैं: ग्राहक, ऑर्डर और उत्पाद (+ 1 पिवोट टेबल ऑर्डर_प्रॉडक्ट)। ग्राहक ऑर्डर करने के लिए एक से कई जुड़े हुए हैं। ऑर्डर कई से कई उत्पादों से जुड़े हुए हैं।

Customers 1-->N Orders N<-->N Products 

मैं ग्राहक मॉडल पर एक विधि चाहूंगा जो ग्राहक खरीद रहे उत्पादों की एक सूची पुनर्प्राप्त करे।

बेहतर समझने के लिए, मान लें कि उत्पाद उपभोग योग्य हैं।

के लिए उदाहरण के ग्राहक # 1 जगह कर सकते हैं:

  • आदेश # 1 उत्पाद ए, बी और सी के लिए;
  • उत्पाद ए, सी और डी के लिए आदेश # 2;
  • उत्पाद सी और ई के लिए आदेश # 3;

... और परिणाम मैं प्राप्त करना चाहते हैं के साथ उत्पाद ए, बी, सी, डी और ई एक संग्रह

मॉडल हैं (मक्खी पर छद्म कोडित):

class Product extends Eloquent { 

    public function orders() 
    { 
     return $this->belongsToMany('Order'); 
    } 

} 

class Orders extends Eloquent { 

    public function customer() 
    { 
     return $this->belongsTo('Customer', 'customer_id'); 
    } 

    public function products() 
    { 
     return $this->belongsToMany('Product'); 
    } 

} 

class Customers extends Eloquent { 

    public function orders() 
    { 
     return $this->hasMany('Orders', 'customer_id'); 
    } 

    public function products() 
    { 
     // What to put here ??? 
    } 

} 
+0

आप हैमैनी थ्रू का उपयोग करने में सक्षम हो सकते हैं और (आमतौर पर-अंतर्निहित) पिवट तालिका को लक्षित कर सकते हैं। कुछ 'वापसी $-- masManyThrough (' ऑर्डर ',' ऑर्डर प्रोडक्ट ') -> (' उत्पाद ') के साथ कुछ;' लेकिन अगर यह काम नहीं करता है तो आपको उस विधि में कुछ मैन्युअल काम करना होगा और एक प्रश्न वापस करें। यह बहुत कठिन नहीं होगा (केवल एक रिश्ते की सुविधा के बिना आप एक प्रश्न बना सकते हैं) लेकिन यह एक मानक रिश्ते के रूप में सुंदर नहीं होगा। – alexrussell

+0

@alexrussell: क्या मुझे इसके लिए पिवट तालिका के लिए एक मॉडल बनाने की आवश्यकता है? इसके अलावा, मेरे कुंग-फू एलोक्वेंट लो-स्तरीय क्वेरी सिस्टम के साथ इतना मजबूत नहीं है, क्या आप वास्तविक कोड (उत्तर के रूप में, शायद) बता सकते हैं? – St0rM

+0

हाँ मुझे लगता है कि आपको ''> हैमैनी थ्रू() -> के साथ()' विधि का उपयोग करने के लिए पिवट तालिका को मॉडल करने की आवश्यकता होगी, अन्यथा लैरवेल को नहीं पता कि पिवोट टेबल को कैसे जोड़ना है (जो आप हैं ' 'हैमनी थ्रू' के बाद 'उत्पाद' तालिका में छोड़ दिया गया है (जो कि पिवट तालिका का 'हैनी' है)। दूसरी तरफ 9as की संभावना है कि 'हैमनी थ्रू' विधि काम नहीं करेगी, मैं देखूंगा कि मैं आपके लिए क्या कर सकता हूं। – alexrussell

उत्तर

2

@ deczo के जवाब देने के लिए धन्यवाद, मैं आइटम को पुनः प्राप्त करने के लिए एक एकल क्वेरी विधि प्रस्तुत करने में सक्षम था:

public function items() 
{ 
    $query = DB::table('items')->select('items.*') 
     ->join('item_order', 'item_order.component_id', '=', 'items.id') 
     ->leftJoin('orders', 'item_order.order_id', '=', 'orders.id') 
     ->leftJoin('customers', 'customers.id' , '=', 'orders.customer_id') 
     ->where('customers.id', $this->id) 
     ->distinct() 
     ->orderBy('items.id'); 

    $eloquent = new Illuminate\Database\Eloquent\Builder($query); 
    $eloquent->setModel(new Item); 
    return $eloquent->get(); 
} 
1

मैं इस एक के लिए आसान संबंध विधि नहीं सोच सकते हैं, लेकिन यहाँ एक समाधान है:

$productsIds = DB::table('customers') 
    ->leftJoin('orders', 'orders.customer_id', '=', 'customers.id') 
    ->join('order_item', 'order_item.order_id', '=', 'orders.id') 
    ->leftJoin('items', 'order_item.item_id' , '=', 'items.id') 
    ->distinct() 
    ->get(['items.id']); 

$productsIds = array_fetch($productsIds, 'id'); 

$productsCollection = Product::whereIn('id', $productsIds); 
+0

धन्यवाद @ डेक्ज़ो, मैं इसे आज़माने वाला हूं। और इससे मुझे यह समझने में भी मदद मिली कि डीबी ऑब्जेक्ट कैसे काम करता है :-) – St0rM

+0

मुझे लगता है कि यह सिर्फ एक -> कहां ('customers.id', $ this-> id) याद करता है। बीटीडब्ल्यू, डीबी ऑब्जेक्ट से सीधे संग्रह प्राप्त करने के लिए एक बेहतर तरीका है? अगर मैं सही ढंग से समझता हूं, तो यह दो प्रश्न बनाता है और पहले के बाद मेरे पास पहले से ही सबकुछ है। – St0rM

+0

हां, किसी दिए गए उपयोगकर्ता के लिए आपको बस उस वक्तव्य को जोड़ना होगा जैसा आपने उल्लेख किया है। एलोक्वेंट संग्रह के बारे में - डीबी क्वेरी बिल्डर से आपको एलोक्वेंट परिणाम (मॉडल/मॉडल का संग्रह) नहीं मिलता है, इसलिए एक ही क्वेरी में इसे करने का एकमात्र तरीका शुरुआत से उत्पाद मॉडल का उपयोग करना है। उस क्वेरी को खोजने का प्रयास करें और मुझे बताएं कि आपको किसी मदद की ज़रूरत है –

0

@ deczo का जवाब शायद ठीक काम करता है, और शायद एक बहुत अधिक performant है सभी डेटा कमी डेटाबेस में ही किया जाता है, लेकिन यहां के रूप में एक 'शुद्ध Laravel' तरीका है कि निस्संदेह अधिक पठनीय है:

use Illuminate\Database\Eloquent\Collection; 

class Customer extends Eloquent 
{ 
    ... 
    public function products() 
    { 
     $products = new Collection; 
     foreach ($this->orders as $order) { 
      $products->merge($order->products); 
     } 

     return $products; 
    } 
} 

ध्यान दें कि यह विधि सामान्य संबंध तरीकों की तरह काम नहीं होगा - जिसके परिणामस्वरूप संग्रह आप प्राप्त करने के लिए विधि को कॉल करें (यानी $products = $customer->products();) और आप इसे संपत्ति के रूप में एक्सेस नहीं कर सकते जैसे आप संबंधों के साथ कर सकते हैं (यानी आप $products = $customer->products; नहीं कर सकते हैं)।

इसके अलावा, मैं Illuminate\Database\Eloquent\Collection#merge() विधि की मेरी समझ पर जा रहा हूं कि यह स्वचालित रूप से DISTINCT-जैसी चीज करता है। यदि नहीं, तो आपको $collection->unique() थोड़ी सी चीज़ करना होगा।

+0

बहुत बहुत धन्यवाद, यह वही है जो मैं अभी कर रहा हूं और पुष्टि करना अच्छा है। जहां तक ​​मैं समझता हूं, मुख्य समस्या प्रदर्शन है (मुझे लगता है कि यह एन + 1 प्रश्न उत्पन्न करता है)। विलय वास्तव में एक अद्वितीय (लेकिन छोड़े गए) संग्रह को वापस कर देता है, जिसे आसानी से सॉर्टबी ('आईडी') के साथ सॉर्ट किया जा सकता है। – St0rM

+0

हाँ बिल्कुल - निष्पादक नहीं है लेकिन कोड पढ़ने में आसान है, इसलिए यह आपके डेटा के आकार पर निर्भर करता है और चाहे आप प्रदर्शन हिट कर सकते हैं या नहीं। – alexrussell

3

यह एक बहुत-से-कई संबंध है, लेकिन के रूप में तालिका आदेश के साथ पिवट तालिका।

class Customers extends Eloquent { 

    public function orders() 
    { 
     return $this->hasMany('Orders', 'customer_id'); 
    } 

    public function products() 
    { 
     return $this->belongsToMany('Products', 'orders', 'customer_id', 'product_id'); 
    } 
} 

मैं पिछले दो पैरामीटर शामिल कर लिए, लेकिन अगर आप singular_id पैटर्न का पालन वे बाहर छोड़ दिया जा सकता है।

+0

वह * शानदार * है। धन्यवाद :-) – St0rM

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