ایجاد رابطه‌ی many to many در لاراول به چه شکل است؟

برای ایجاد رابطه‌ی چند به چند یا many to many در لاراول نیاز به یک جدول واسط یا pivot داریم.

فرض من بر این است که قصد دارم بین دو جدول users و categories ارتباط چند به چند برقرار کنم. یعنی یک کاربر می‌تواند عضو چند دسته باشد و هر دسته می‌تواند چندین و چند کاربر داشته باشد. پس همانطور که قبل‌تر اشاره کردم علاوه بر دو جدول یک جدول واسط یا همان pivot table نیاز است که به صورت زیر جداول را تعریف می‌کنم:

users
categories
category_user

در لاراول به صورت پیشفرض برای جدول واسط ترکیب نام دو جدول به صورت مفرد استفاده می‌شود و ترتیب نیز بر اساس حروف الفبای انگلیسی است که در بالا ملاحظه می‌کنیم.

جدول category_user نیز شامل سه ستون خواهد بود که طبیعتاً باید با ستون‌های متناظر خود در جداول دیگر همخوانی داشته باشند:

id
user_id
category_id

به سراغ مدل‌های مربوطه می‌روم تا بتوانم ارتباط را برقرار کنم که به طور خلاصه در هر مدل، ارتباط با مدل دیگر به صورت زیر برقرار خواهد شد:

User.php

public function categories()
{
	return $this->belongsToMany(Category::class,'category_user','user_id','category_id');
}

Category.php

public function users()
{
	return $this->belongsToMany(User::class,'category_user','category_id','user_id');
}

در مدل‌ها برای ایجاد روابط اگر از استانداردهای نامگذاری لاراول تبعیت کرده باشیم، نیازی نیست پارامترهای دوم و سوم و چهارم را تعیین کنیم، کما اینکه تعریف کردنشان مشکلی ایجاد نمی‌کند و من آن‌ها را مشخص کرده‌ام.

در سمت کنترلر هم چیزی مشابه زیر داریم که من برای موارد store و update نمونه‌ای را ایجاد کرده‌ام و مشخص است که چطور از attach و sync برای این موارد استفاده شده:

public function store(UserCreateRequest $request)
{

if ($request->hasFile('profile_image')) {

	$imageName = time() . '.' . $request->profile_image->extension();

	$user = User::create([
		'name' => $request['name'],
		'email' => $request['email'],
		'profile_image' => $imageName,
	]);

	$user->categories()->attach(request('category_id'));

	$request->profile_image->move(public_path('images'), $imageName);
	
} else {

	$user = User::create([
		'name' => $request['name'],
		'profile_image' => 'nopic.jpg',
		'email' => $request['email'],
	]);

	$user->categories()->attach(request('category_id'));
}

return redirect(route('users.create'))->with('success', 'عملیات افزودن با موفقیت انجام پذیرفت');
}
public function update(User $user, UserUpdateRequest $request)
{

	if ($request->hasFile('profile_image')) {

		$imageName = time() . '.' . $request->profile_image->extension();

		$user->update([
			'name' => $request['name'],
			'email' => $request['email'],
			'profile_image' => $imageName,
		]);

		$user->categories()->sync(request('category_id'));

		$request->profile_image->move(public_path('images'), $imageName);
	} else {

		$user->update([
			'name' => $request['name'],
			'email' => $request['email'],
		]);

		$user->categories()->sync(request('category_id'));
	}

	return redirect(route('users.index'))->with('success', 'به روز رسانی با موفقیت انجام پذیرفت');
}

در ویو نیز به فرض قصد نمایش دسته‌های مربوط به یک کاربر را دارم، برای نمونه به صورت زیر عمل می‌کنم:

@foreach($user->categories as $category)
	{{ $category->title }}
@endforeach

به طور بسیار ساده و خلاصه این روال ایجاد و استفاده از روابط چند به چند در لاراول بود.

درباره نویسنده: احسان

مطالب زیر را حتما بخوانید