Laravel HasMany قضية علاقة عكسية

0

لنضع مثالاً:

لدي صفحة تعرض جميع الفواتير.

يمكن لمسؤول الموقع تصفية النتائج مع العميل من خلال البحث بأسماء أو أسماء أخيرة.

نموذج الفاتورة

    public function clients()
{
    return $this->belongsTo('App\Client');
}

نموذج العميل

    public function invoices() {

    return $this->hasMany('App\Invoice');
}

لنفترض أن المشرف يريد تصفية الفواتير حسب العملاء ، ويكتب على سبيل المثال "Jhon"

جهاز التحكم الخاص بي:

1- اختيار العميل حيث اسم مثل "Jhon" أو اسم العائلة مثل LIKE "Jhon"

2- إذا أعاد الاستعلام $ مصفوفة مع الكثير من العملاء لديهم اسم Jhon.

كيف سأحصل على فواتير لهذا العملاء باستخدام العلاقة ؟؟؟

3 الاجابة

0

من فضلك ضع في اعتبارك أن Toyi هو أفضل طريقة للقيام بذلك ، كنت أحاول فقط جعل هذا الأمر بسيطًا قدر الإمكان بالنسبة لك ، ولكنه 100 ٪ حول Eager Loading لأنه أكثر كفاءة.

إذن ، استخدامك لعلاقة واحد لكثير ، حيث يكون نموذج عملائك هو الأصل ، ولكن الآن جعل نموذج الفاتورة معكوسًا ، فأول شيء عليك أولاً التأكد من أن كل فاتورة تحتوي على "رقم_العميل" الصحيح الذي يخزن معرف كل عميل في كل فاتورة. أود أيضًا أن أكون آمنًا وأتأكد من أنه يبحث عن المعرّف الصحيح لتعيين نماذجك على هذا النحو.

نموذج العميل

public function invoices() {
    return $this->hasMany('App\Invoice', 'client_id');
}

نموذج الفاتورة

public function clients() {
    return $this->belongsTo('App\Client', 'client_id');
}

ثم في وحدة التحكم الخاصة بك يمكنك سحب تلك البيانات مثل ذلك.

$client = Client::where('name','like', '%' . Input::get('name') . '%')->orWhere('lastname', 'like', '%' . Input::get('name') . '%')->get();

foreach($client->invoices as $invoice) {
   echo $invoice->title; //Or What ever data you need to pull from your invoice.
}

يرجى ملاحظة أنني أضفت أيضًا الطريقة التي ستضيف بها هذا الإدخال إلى عبارة orWhere و where. ضع في اعتبارك أن "٪" يساعد في التحقق من نسبة غير متوقعة في مربع إدخال المستخدم.

مع حريصة التحميل

تحديث لهذا المنصب أرى أن لديك الرمز التالي:

$invoices = Facture::with('client')->where(function($q) { 
   $key = Input::get('client'); 
   $q->where('nom', 'LIKE', '%'.$key.'%'); 
   $q->orWhere('prenom', 'LIKE', '%'.$key.'%'); 
})->get();

ما سأفعله هو أنني سأمرر المدخلات بهذه الطريقة لأنها قد تصلح الخطأ.

$key = Input::get('client');
$invoices = Facture::with('client')->where(function($q) or ($key) {  
   $q->where('nom', 'LIKE', '%'.$key.'%'); 
   $q->orWhere('prenom', 'LIKE', '%'.$key.'%'); 
})->get();

السبب وراء ذلك هو أن Eager يتم تحميله لأي سبب من الأسباب لا يمكنه وضع السلاسل والمتغير من الجانب الخارجي ، لذا قمت بتعيين المتغير إليه عن طريق تمريره مع الوظيفة وقمت بإدخال $ key قبل الفواتير $. إذا كان ذلك منطقيًا. هتاف أمل هذا يعمل لك.

:مؤلف
0

يمكنك القيام بذلك في كلا الاتجاهين ، اعتمادًا على ما يناسبك.

الفاتورة (حيث):

Invoice::whereHas('client', function ($query){
    $query->where('name', 'like', 'Jhon')
        ->orWhere('lastname', 'like', 'Jhon');
})->get();

العميل (flatMap + علاقة الفواتير):

Client::where('name', 'like', 'Jhon')
    ->orWhere('lastname', 'like', 'Jhon')
    ->get()
    ->flatMap->invoices;

ضع في اعتبارك أن الخيار الثاني يعاني من N + 1 ما لم يكن with('invoices') يتم استدعاء قبل تنفيذ الاستعلام (-> get ()) ؛

:مؤلف
0

يجب عليك تسمية علاقاتك بالصيغة المفرد أو الجمع للشيء الذي يمثلونه حتى لا تضيع في وقت لاحق في تطوير مشروعك. في حالتك،

public function clients() {
    return $this->belongsTo('App\Client', 'client_id');
}

يجب أن تكون مفردة ، لأن الفاتورة تخص عميل واحد فقط :

public function client() {
    return $this->belongsTo('App\Client', 'client_id');
}

الآن ، للإجابة على سؤالك بالفعل ، نظرًا لأنك تقوم بإدراج الفواتير ، فإنني أنصحك بالبدء بنموذج الفاتورة. شيء من هذا القبيل سيفي بالغرض:

$invoices = Invoice::with('client')->where(function($q){
    $q->where('firstname', 'LIKE', 'Jhon');
    $q->orWhere('lastname', 'LIKE', 'Jhon');
})->get();

لاحظ ال with('client') ، سيكون ذلك مفيدًا لأنه سيحمّل العميل جميع فواتيرك بحماس ، لذلك لن ينتهي بك الأمر إلى استعلام آخر لكل تكرار في foreach الخاص بك. الوثائق حول التحميل المتلهف متاحة هنا

شيء آخر يمكنك القيام به: بدلاً من استخدام "أعجبني" ، استخدم "REGEXP".

$invoices = Invoice::with('client')->where(function($q){
    $q->where('firstname', 'REGEXP', '([[:<:]])Jhon');
    $q->orWhere('lastname', 'REGEXP', '([[:<:]])Jhon');
})->get();

سيعطيك فواتير كل شخص حيث يبدأ اسم العائلة أو اسم العائلة بـ Jhno. عديمة الفائدة مع كلمة "Jhon" ، ولكنها مفيدة جدًا في كثير من الحالات: "J" ستجد كل Jack ، Jhon ، John ، Joe ...

آخر شيء استخدمته with('client') في الأمثلة الخاصة بي لأنني أفترض أنك قمت بتصحيح اسم العلاقة. إذا لم يكن الأمر كذلك ، يجب عليك استخدام "العملاء" حيث إنه اسم العلاقة في نموذج الفاتورة :)

:مؤلف

أسئلة ذات صلة

فوق
قائمة طعام