لارافيل, Model / 2024-03-03

العلاقة One To Many في لارافيل، كيفية إنشاؤها، وإدخال وإستخراج وفلترة البيانات.

العلاقة One To Many في لارافيل، كيفية إنشاؤها، وإدخال وإستخراج وفلترة البيانات.

2024-03-03 وقت القراءه : 6 دقائق

جدول المحتويات


ما هي علاقة One To Many Relationship؟

تسمى هذه العلاقة أيضا hasMan، وتستخدم عندما نريد ربط صف  في جدول معين مع صفوف أخرى في جدول أخر.

لفرض اننا نقوم ببرمجة موقع تجارة إلكترونية، ويوجد لدينا جدول brand وينتمي لهذا الـ brand مجموعة من Product هنا تسمى العلاقة One وهو brand إلى many وهو Product، مثال أخر لنفرض أنك تبرمج موقع إخباري ويوجد لكل مقال تعليقات هنا نستخدم علاقة one to many بحيث أن المقال له مجموعة من التعليقات، ومجموعة من التعليقات تنتمي لمقال واحد.


إنشاء Models و ملفات Migration

لتنفيذ علاقة one to many فإننا نحتاج إلى جدولين، هنا سوف أستخدم جدول brand بحيث ينتمي له مجموعة من products.

public function up()
{
    Schema::create('brands', function (Blueprint $table) {
        $table->id('id');
        $table->string('name');
        $table->timestamps();
    });
}


public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->id('id');
        $table->forignId('brand_id')->constrained();
        $table->string('name');
        $table->string('slug');
        $table->double('price');
        $table->integer('qty');
        $table->timestamps();
    });
}


كما نلاحظ أنه في جدول products تم إضافة brand_id ، فهو الحقل الذي سوف يربط بين brand و product، مع العلم أن التسمية يجب أن تكون إسم الجدول الأب لكن مفرد ومن ثم ـid، لكن لو تم تغيير هذا الإسم مثلا إلى brands_id فيجب تعريف ذلك في الـ model.


إنشاء العلاقة One To Many في الـ Model

في Brand Model يجب تحديد علاقتة مع Product Model من خلال إضافة دالة product وبما أن brand يحتوي على أكثر من product فيجب أن يرجع  علاقة hasMany من جدول products

class Brand extends Model
{
    public function products()
    {
        return $this->hasMany(Product::class);
    }
}

لكن إذا كان forignKey أي حقل العلاقه بإسم غير brand_id مثلا إذا كان brands_id فيجب أن يتم تحديد ذلك في العلاقة، من خلال إضافة باراميتر ثاني يحتوي على إسم الحقل

public function products()
{
    return $this->hasMany(Product::class,'brands_id');
}


تحديد العلاقة العكسية Inverse في علاقة Many To Many.

كما قمنا بتعريف العلاقة hasMany في Brand Model، نستطيع أيضا تحديد العلاقة العكسية، ففي Product Model نقوم بإضافة دالة جديده بإسم brand والتي ترجع belongsTo بمعنى ينتمي إلى

class Product extends Model
{
    public function brand()
    {
        return $this->belongsTo(Brand::class);
    }
}

كذلك إذا كان تم تغيير إسم الحقل فيجب تعريف ذلك بالعلاقه كما بالمثال أعلاه.


إسترجاع البيانات في علاقة One To Many.

بعد تحديد العلاقة بين الموديل، نستطيع الأن جلب البيانات 

$brand = Brand::find(1);
$products = $brand->products;

هذه الجملة ترجع brand بالمعرف id=1 وجميع المنتجات التي تتبع هذا brand، وبشكل مشابة نستطيع إرجاع إسم المنتج مع نوع brand وذلك من خلال العلاقة العكسية

$product = Product::find(1);
$brand = $product->brand;
dd($brand->name);


إدخال البيانات في علاقة One To Many

$brand = Brand::find(1);


$product = new Product();
$product->name = 'iPhone X';
$product->slug = 'iphone-x';
$product->price = '899.99';
$product->qty = 10;
$product->description = 'Some description';


// Saving related model
$brand->products()->save($product);

كما نستطيع أيضا إستخدام saveMany عوضا عن إستدام save 


عرض البيانات في علاقة One To Many

لجلب جميع brand مع المنتجات التابعة له

$brands = Brand::select('id','name')->with('products:id,brand_id,name,price')->get();
return $brands;
[
    {
    "id": 1,
    "name": "Samsung",
    "products": [
        {
        "id": 3,
        "brand_id": 1,
        "name": "iPhone X",
        "price": 899.99
        }
        ]
    },
    {
    "id": 2,
    "name": "Apple",
    "products": [
        {
        "id": 1,
        "brand_id": 2,
        "name": "Iphone 11",
        "price": 1000
        },
        {
        "id": 2,
        "brand_id": 2,
        "name": "IPhone Pro Max",
        "price": 1500
        }
        ]
    }
]

لجلب المنتجات مع إسم البراند التابع له

$brands = Product::select('id','name','brand_id','price')->with('brand:id,name')->get();
return $brands;
[
    {
        "id": 1,
        "name": "Iphone 11",
        "brand_id": 2,
        "price": 1000,
        "brand": {
        "id": 2,
        "name": "Apple"
        }
    },
    {
        "id": 2,
        "name": "IPhone Pro Max",
        "brand_id": 2,
        "price": 1500,
        "brand": {
        "id": 2,
        "name": "Apple"
        }
    },
    {
        "id": 3,
        "name": "iPhone X",
        "brand_id": 1,
        "price": 899.99,
        "brand": {
        "id": 1,
        "name": "Samsung"
        }
    }
]


فلترة البيانات في علاقة One To Many

إذا أردنا أن نحصل على البراند مع المنتجات التابعة لها لكن سعرها فوق 500 وأن يتم ترتيبها حسب الإسم

$brands = Brand::select('id', 'name')->with(['products' => function ($q) {
    $q->select('id', 'name', 'price','brand_id')
        ->where('price', '>', 500)
        ->orderBy('name', 'asc');
}])->get();
return $brands;

كما نلاحظ أنه من جدول Brand يجب أن يتم الحصول على id ومن جدول product يجب الحصول على brand_id لأنه هو الذي يربط بين الجدولين.


حذف البيانات في علاقة One To Many.

حذف البيانات في علاقة one to many تشبة طريقة الإدخال حيث بداية يجب الحصول على الأب وهو brand ومن ثم إستخدام العلاقة products لحذف جميع المنتجات التابعة له.

لحذف منتجات البراند بالمعرف id=1

$brand = Brand::find(1);
$brand->products()->delete();

التعليقات
Mohamed Osama
منذ سنتين

شكرا ياغلى الله يوفقك ارجو ان تفتح قناه على يوتيوب والله محتواك قوى جدا من شخص محترف الرجاء كمل فى العلاقات شكرا اخى العزيز

عبدالسميع العاشق
منذ سنتين

عند طلب البيانات بعلاقة تحصل عليها بهذا الشكل { \"id\": 2, \"name\": \"IPhone Pro Max\", \"brand_id\": 2, \"price\": 1500, \"brand\": { \"id\": 2, \"name\": \"Apple\" } }, هل يمكن اخلي حقول جدول البراند مثل حقول المنتج بمعنى لا يوجد غلاف باسم براند يغطيهم مثل هذا { \"id\": 2, \"name\": \"IPhone Pro Max\", \"brand_id\": 2, \"price\": 1500, \"brand_id\": 2, \"brand_name\": \"Apple\" },

زائر
منذ سنتين

كنت انتظر حديتك عن العلاقات شكرا خصوصا معقدة منها

ABO OMAR
منذ سنتين

شرح جميل كافي ووافي

زائر
منذ سنة

السلام عليكم اخي هنالك syntax error في products migration بالضبط في ال foreignId

إضافة تعليق
Loading...