سلام و درود خدمت همه ی دوستان و عزیزان راکتی
اقا من یک پروژه ای دارم که نیاز به ارتباط چند به چند یک جدول با خودشه.
برای درک نیاز این موضوع مثال برنامه اینستا رو داشته باشید که هر کار بر چندین دنبال کننده و چندین دنبال شونده داره
موضوع رو در لینکی که زیر قرار میدم میتونید بهتر ببینیدو خودش هم راهنمایی داره که من درست متوجهش نشدم.
many-to-many from the same table
حالا سناریو خودم رو توضیح میدم که چی هست صحنه که دوستان بهتر بتونن بنده رو راهنمایی کنن
من دارم برای یه رستوران غذای آماده پروژه ای مینویسم
موضوع برای غذا های این پروژه هست در زمانی که میخوام سفارشی رو ثبت کنم و موجودی اون غذا کم کنم.
قضیه اینطوریه که در غذای آمده ای مثلا شما صد پرس چلو داری ، پنجاه تا جوجه ، پنجاه تا کوبیده (فرض مسئله)
خب برای فروش سفارش ها به صورت چلو جوجه کباب و چلو کباب کوبیده هست که هم چلو توشه هم کوبیده یا جوجه
چلو یه موجودی داره و جوجه هم همینطور
جوجه به تنهایی و چلو هم به تنهایی قابل فروش هست
یعنی نمیشه بگیم فقط غذای چلو جوجه کباب داریم و چلوی تنها رو نمیدیو یا جوجه ی تنها رو نمیتونیم بدیم
پس قرار دادن موجودی برای چلو جوجه کباب بی معنی میشه چون با فروش اون باید یکی از موجودی چلو ها و یکی از موجودی جوجه ها کم بشه
حالا اینجا یک غذا (چلو جوجه کباب ) دو تا پدر (چلو و جوجه ) رو داره و چلو هم دو تا فرزند (چلو جوجه کباب و چلو کباب کوبیده ) رو داره
در کل قراره محصولی که پدری داره موجودی ای نداشته باشه و با فروش اون از موجودی تمام پدر هاش یکی کم بشه
مثلا با فروش چلو جوجه کباب از موجودی دو پدرش که چلو و جوجه هست یکی کم بشه
تنها روشی ک ب فکرم میرسه رابطه چند به چند جدول محصولاتم با خودشه
جدول محصولات (که غذا هم شاملشه) و دسته بندیمم به شکل زیره:
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
});
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->integer('price')->default(0);
$table->integer('stock')->default(0);
});
Schema::create('category_product',function (Blueprint $table){
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->unsignedBigInteger('product_id');
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->primary(['category_id','product_id']);
});
بخش ثبت محصولات (غذا ها و ... )در حالت فعلی رو میتونید ببینید که هنوز این بحثی که گفتم بهش اضاف نشده و برای حساب کتاب موجودی هاش لازمه واقعا
اقا بر اساس لینکی که اول فرستادم با بررسی های خیلی بیشتر موفق به انجامش شدم
فقط کافیه یه جدول دیگه با هر نامی که دوس داری ایجاد کنی
داخل جدول جدید دو تا ستون باز هم با هر نامی که دوس دارید ایجاد میکنید و مرتبط میکنید جفتشو به عنوان کلید خارجی به کلید اصلی جدولی که میخوایید ارتباط چند به چند با خودش داشته باشه
توی مثال من parent_id و child_id کلید خارجی برای id از جدول prodcuts هستند
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->integer('price')->default(0);
$table->integer('stock')->default(0);
});
Schema::create('foods',function (Blueprint $table){
$table->unsignedBigInteger('parent_id');
$table->foreign('parent_id')->references('id')->on('products')->onDelete('cascade');
$table->unsignedBigInteger('child_id');
$table->foreign('child_id')->references('id')->on('products')->onDelete('cascade');
$table->primary(['parent_id','child_id']);
});
در مرحله ی اخر هم این ارتباط رو در مدل خودتون قرار میدین
نیاز نیست برای این جدول جدید مدل بسازید
من فقط در مدل product این قطعه کد پایین رو قرار دادم
public function parents() {
return $this->belongsToMany(Product::class, 'foods', 'child_id', 'parent_id');
}
public function childs() {
return $this->belongsToMany(Product::class, 'foods', 'parent_id', 'child_id');
}
در رابطه با طریقه ی کم کردن موجودی محصولات پدر در یک حلقه برای هر محصول قطعه کد زیر رو زدم
که به این صورت هست که اگر این محصول پدری داره بره از هر پدرش موجودی رو کم کنه اگر هم نداره فقط از خودش کم کنه
if (Product::find($product['product_id'])->parents->count()){
foreach (Product::find($product['product_id'])->parents as $parent){
DB::table('products')->where('id',$parent['id'])->decrement('stock', $product['count']);
}
}else{
DB::table('products')->where('id',$product['product_id'])->decrement('stock', $product['count']);
}
سلام!
فکر میکنم اگر جدول غذاهای پایه ( برنج ، مرغ ، کباب و ... ) جدا باشه و یک جدول هم برای غذاهای ترکیبی ( برنج + مرغ ) ایجاد بشه بهتر باشه.
و جدول غذای ترکیبی رابطه یک به چند با جدول پایه داشته باشه و موقع سفارش غذای ترکیبی ، لیست غذای های پایه فراخوانی و کم بشه.
جدول ترکیبی میتونه هم یک عنوان بگیره تا به جای برنج و مرغ ، کاربر بنویسه چلومرغ
مرسی ایده ی جالبی بود
ولی در مرحله ی اول این که چون قراره این محصولات نمایش داده بشن (تصویری که در انتها قرار دادم) انتخاب محصولات مختلف از جداول مختلف که یک ویژگی مشترک دارن همشون و بعد فهمیدن این که ایدی این محصول برای کدوم جدول و محصوله برای افزودن، حذف ، ویرایش به شدت به نظرم حجم کد رو بالا میبره و دستورات شرطی رو زیاد میکنه
برای قضیه که گفتید به جای برنج و مرغ کاربر مینویسه چلو مرغ، بله قرار نیست کاربر دوتا رو برای یک سفارش بنویسه
در تعریف محصول، کاربر میزان پرس برنج و سیخ جوجه رو که باید جدا مشخص کنه و جدا هم میتونه بفروشه پس به صورت جدا تعریف و میتونن انتخاب بشن
اما محصولی که دارای پدر هست موقع تعریف پدر هاش مشخص میشن مثلا همونطور که گفتم غذایی با اسم چلو مرغ دارای دو پدر چلو و مرغ هست
من توی دسته بندی ها هم رابطه ای که گذاشتم یک محصول میتونه چند دسته بندی داشته باشه و ب راحتی انتخاب و نمایش داده میشه
سلام
برای اینکه دوستان بتونن بهتر به شما دوست عزیز کمک کنن اگه بتونید یک فلو چارت ارائه بدید راحت تر می شه🌹
@salar.mohammad2013
ب نظرم تا جایی که تونستم کامل توضیح دادم
چیزی که نیاز هست ارتباط چند به چند یک جدول با خودشه
مثل قضیه ای که لینکش رو در ابتدای بحث قرار دادم
اگر جایی ابهام هست سوال کنید توضیح بدم
@mohaligateway
اقا بر اساس لینکی که اول فرستادم با بررسی های خیلی بیشتر موفق به انجامش شدم
فقط کافیه یه جدول دیگه با هر نامی که دوس داری ایجاد کنی
داخل جدول جدید دو تا ستون باز هم با هر نامی که دوس دارید ایجاد میکنید و مرتبط میکنید جفتشو به عنوان کلید خارجی به کلید اصلی جدولی که میخوایید ارتباط چند به چند با خودش داشته باشه
توی مثال من parent_id و child_id کلید خارجی برای id از جدول prodcuts هستند
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->integer('price')->default(0);
$table->integer('stock')->default(0);
});
Schema::create('foods',function (Blueprint $table){
$table->unsignedBigInteger('parent_id');
$table->foreign('parent_id')->references('id')->on('products')->onDelete('cascade');
$table->unsignedBigInteger('child_id');
$table->foreign('child_id')->references('id')->on('products')->onDelete('cascade');
$table->primary(['parent_id','child_id']);
});
در مرحله ی اخر هم این ارتباط رو در مدل خودتون قرار میدین
نیاز نیست برای این جدول جدید مدل بسازید
من فقط در مدل product این قطعه کد پایین رو قرار دادم
public function parents() {
return $this->belongsToMany(Product::class, 'foods', 'child_id', 'parent_id');
}
public function childs() {
return $this->belongsToMany(Product::class, 'foods', 'parent_id', 'child_id');
}
در رابطه با طریقه ی کم کردن موجودی محصولات پدر در یک حلقه برای هر محصول قطعه کد زیر رو زدم
که به این صورت هست که اگر این محصول پدری داره بره از هر پدرش موجودی رو کم کنه اگر هم نداره فقط از خودش کم کنه
if (Product::find($product['product_id'])->parents->count()){
foreach (Product::find($product['product_id'])->parents as $parent){
DB::table('products')->where('id',$parent['id'])->decrement('stock', $product['count']);
}
}else{
DB::table('products')->where('id',$product['product_id'])->decrement('stock', $product['count']);
}
آیا مایل به ارسال نوتیفیکیشن و اخبار از طرف راکت هستید ؟