اذهب إلى المحتوى

السؤال

نشر

السلام عليكم, 

اولاً فكرة مشروع هو إظهار اسعار منتجات 
عندي كم جدول :
Product, ProductPrice, Region, Wilayat, Store, Category
سويت migrationو Seeders واتوقع سويت Model

المشكلة انا سيء ف علاقات بين الجداول والبيانات
المهم سويت التالي  ل Product model

class Product extends Model
{
    use HasFactory;

    protected function category(){

        return $this->belongsTo(Category::class);
    }

    protected function productPrice(){
        return $this->belongsToMany(ProductPrice::class);
    }

كذلك مودل ProductPrice
 

class ProductPrice extends Model
{
    use HasFactory;

    public function product(){
        return $this->hasMany(Product::class)->withPivot('product_id');
    }

    public function store(){
        return $this->hasMany(Store::class);
    }

 

ف الكنترولر 
 

public function index()
    {
        $products = ProductPrice::with('Product')->get();
        return view('test', compact('products'));
    }

 

قرأت Laravel Docs وحصلت شيء اسمه Pivot بس ما فهمت له 
https://laravel.com/docs/9.x/eloquent-relationships#retrieving-intermediate-table-columns

كذلك قرأت هذي المقالة https://www.itsolutionstuff.com/post/laravel-9-many-to-many-eloquent-relationship-tutorialexample.html
 

المطلوب اطلع اسماء المنتجات واقدر اعرض سعر المنتج واي محل Store يبيعه ووين.

اعتذر على ازعاج وارفق لكم المشروع.

 ديسكورد MOGr488#4281
 

omprices.7z

Recommended Posts

  • 1
نشر

لديك بعض الأخطاء في تعريف العلاقات، عندما نتحدث عن السعر فهو ينتمي لمنتج و ينتمي لمتجر:

ProductPrice:

belongsTo Product
belongsTo Store

أما عندما نتحدث عن المنتج فنقول أن المنتج لديه عدة أسعار، و موجود في عدة متاجر:

Product

hasMany ProductPrice
belongsToMany Store

أما عندما نتحدث عن المتجر فنقول أنه يبيع عدة منتجات و لديه عدة أسعار:

Store:

hasMany ProductPrice
belongsToMany Product

العلاقة بين المتجر و المنتج هي كثير لكثير و الجدول الوسيط هو product_prices.

 

توابع العلاقات نُعرفها عامة public و ليس protected، أيضاً عند تعريفك للمفاتيح الأولية لم تتبع العُرف لارافل يستخدم id و عليه يجب عليك إعادة تعريف خاصية المفتاح الأولي لكل نموذج و وضع اسم العمود، مثلا في النموذج Product:

protected $primaryKey = 'product_id';

و في النموذج Store:

protected $primaryKey = 'store_id';

و في النموذج ProductPrice:

protected $primaryKey = 'productPrice_id';

و نفس الأمر بالنسبة للبقية.

عليه عند تعريف العلاقات في النموذج ProductPrice نكتب:

public function product() {
  return $this->belongsTo(Product::class, 'product_id', 'product_id');
}

public function store() {
  return $this->belongsTo(Store::class, 'store_id', 'store_id');
}

يجب تمرير أسماء الحقول الثانوية في المعاملات (الثاني و الثالث) لأنك غيرت و لم تتبع العرف في التسمية و إن لم تمرر الأسماء الصحيحة ستحدث أخطاء.

في النموذج Product:

public function prices(){
  return $this->hasMany(ProductPrice::class, 'product_id', 'product_id');
}

public function stores()
{
  return $this->belongsToMany(Store::class, 'product_prices', 'product_id', 'store_id');
}

أما بالنسبة للنموذج Store:

public function prices(){
  return $this->hasMany(ProductPrice::class, 'store_id', 'store_id');
}

public function products()
{
  return $this->belongsToMany(Product::class, 'product_prices', 'store_id', 'product_id');
}

أخيراً في المتحكم يُمكنك جلب البيانات بالشكل الذي تريد مثلاً:

$products = Product::with('prices', 'prices.store')->get();
$stores = Store::with('prices', 'prices.product')->get();

return view('test', compact('products', 'stores'));

في ملف العرض يُمكنك الوصول للبيانات بالشكل التالي:

<h2>Products</h2>
<ol>
    @foreach($products as $product)
        <li>
            {{ $product->productName }}
            <ul>
                @foreach($product->prices as $price)
                    <li>
                        <strong>Store: </strong> {{ $price->store->storeName }} /
                        <strong>Price: </strong> {{ $price->productPrice }}
                    </li>
                @endforeach
            </ul>
        </li>
    @endforeach
</ol>


<hr>

<h2>Stores</h2>
<ol>
    @foreach($stores as $store)
        <li>
            {{ $store->storeName }}
            <ul>
                @foreach($store->prices as $price)
                    <li>
                        <strong>Product: </strong> {{ $price->product->productName }} /
                        <strong>Price: </strong> {{ $price->productPrice }}
                    </li>
                @endforeach
            </ul>
        </li>
    @endforeach
</ol>

قمت ببذر بعض البيانات و كانت النتيجة كالتالي:

pro_stores.thumb.JPG.e924c80bdb4c2a7644e64a1d7446aecb.JPG

ركزت فقط على النماذج الثلاثة Product و ProductPrice  و Store و الحالة التي ذكرتها، بقية النماذج عليك تعريف العلاقات فيها بنفس الشكل.

  • 0
نشر
بتاريخ 3 ساعات قال سالم التوبي2:

لو سمحت ممكن تشرح ايش تسوي With() ؟

تُستخدم with لتحميل العلاقات بشكل حثيث لتقليل عدد الاستعلامات و يُسمى المصطلح باللغة الإنجليزية Eager loading

يُمكنك الإطلاع على: التحميل الحثيث Eager loading لفهم المغزى من إستخدام with، و الهدف كما قلت هو معالجة مشكلة (N+1) خصوصاً عند الوصول للعلاقة على شكل خاصية في الحلقات

يوجد في الرابط أعلاه مثال لنموذج الكتاب (Book) و نموذج الكاتب (Author) و العلاقة واحد لكثير.

عند جلب كافة الكتب ثم في الحلقة نصل لإسم الكاتب عبر العلاقة بالشكل التالي:

$books = Book::all();

foreach ($books as $book) {
   echo $book->author->name;
}

ذلك يعني إستعلام واحد لجلب كافة الكتب، ثم في الحلقة من أجل كل كتاب إستعلام إضافي لجلب الكاتب. و هذا النوع من التحميل يُسمى التحميل الكسول و هنا مُشكلة الإستعلامات  (N + 1)، أما بإستخدام with نقوم بتحميل العلاقة بشكل مُسبق مع الإستعلام الأولي. ( أي إستعلام لجلب كافة الكتب و إستعلام واحد فقط إضافي لجلب الكُتاب)

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...