Laravel Eloquent Many To Many Relationship Explained

Laravel Eloquent Many To Many Relationship Explained

In this post, we will look at one of the mostly yet advanced relationship type Many To Many offered by Laravel Eloquent.

Before proceeding, I assume you should know how One to One and One To Many Relationship works in Laravel.

So let’s dive into Laravel Eloquent’s many to many relationships.

What is Many To Many Relationship?

Many To Many Relationship relate a record in on the table to one or many records in another table, and vice versa. Unlike One to Many and One to One, in this relationship type, the key is the join (pivot table) you define between two tables to link them. A pivot table allows the relationship id from one model to be related to many other models and vice-versa.

One practical example we can think of is products and categories. A category can have many products and a product can relate to many categories, simple isn’t. To have a better understanding of how we can use this relationship, let’s do some coding.

Install Laravel First ?

To start, we will create a fresh Laravel application. Run below command in your terminal to create a new application.

composer create-project laravel/laravel ManyToMany --prefer-dist

Once you have a fresh installation of Laravel, go ahead a setup your database credentials in .env file.

Creating Model and Migrations

Firstly, we will create two models called Product and Category along with their migrations. Run below command to generate models and migrations.

php artisan make:model Category -m
php artisan make:model Product -m

Once, you have models and migration generated update them with the code below:

Category Migration

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->text('description')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('categories');
    }
}

Category Model

// Category.php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    protected $table = 'categories';

    protected $fillable = ['name', 'description'];
}

Product Migration

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->float('price');
            $table->text('description')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Product Model

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $table = 'products';

    protected $fillable = ['name', 'price', 'description'];
}

Now go to your terminal and run below command to migrate both tables to the database.

php artisan migrate

Dummy Date

For the sake of this tutorial, add some dummy categories and products in your database.

Creating Pivot Table

Now, we need to connect these two tables using a link table called Pivot Table. The pivot table is a relationship table which will hold the category_id and product_id in it.

You can store more information in the pivot table, but right now we just need to create a many to many relationships. I will cover using a pivot table to store extra data in a separate post.

Run below command to generate a migration for our pivot table.

php artisan make:migration create_category_product_table

Once you have your migration for category_product table, update the migration with below code.

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoryProductTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('category_product', function (Blueprint $table) {
            $table->engine = 'MyISAM';
            $table->bigIncrements('id');
            $table->integer('category_id')->unsigned();
            $table->integer('product_id')->unsigned();

            $table->foreign('category_id')->references('id')->on('categories');
            $table->foreign('product_id')->references('id')->on('products');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('category_product');
    }
}

In above migration, we are adding three columns in this table, id, category_id and product_id. Pay close attention to the migration, we are also setting the foriegn keys on their respective tables.

Now, run artisan command to migrate this table to the database.

php artisan migrate

Defining Many To Many Relationship in Laravel Eloquent

Finally, it’s time to define Many to Many relationship between Category and Product model using Laravel Eloquent.

Firstly, we know multiple categories belongs to multiple products, so we can add belongsToMany relationship on Product model. Open Product model class and add a new method called catgeories() like below:

/**
 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 */
public function categories()
{
    return $this->belongsToMany(Category::class);
}

Similarly, we know multiple products belongs to multiple categories, so we can define belongsToMany relationship on Category model like below. Add a new method in Category model called products() like below.

/**
 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 */
public function products()
{
    return $this->belongsToMany(Product::class);
}

Creating a Many To Many Relationship

Now let’s create some categories and products, also create a Many To Many relationships between them. Firstly, we will create a few categories like below (How you add products and categories totally depends on you).

use App\Category;

$categories = ['Office Chairs', 'Modern Chairs', 'Home Chairs'];

foreach($categories as $category)
{
    Category::create([
        'name'  =>  $category,
    ]);
}

Now you will have some categories like below in your categories table.

Adding Categories
Adding Categories

Now we will create a product and attach them to a few categories.

$product = Product::create([
    'name'  =>  'Home Brixton Faux Leather Armchair',
    'price' =>  199.99,
]);

$categories = Category::find([2,3]); // Modren Chairs, Home Chairs
$product->categories()->attach($categories);

Above code will create a product and then attach that product to multiple categories.

Adding Product
Adding Product

In the category_product table, you can see product_id 1 have multiple entiries with category_id 2 and 3.

Pivot Example
Pivot Example

That’s how you can create many to many relationships in Laravel Eloquent. Obviously, you can use the inverse of this relationship to attach a category to multiple products.

Retrieving Many To Many Relationship Data

Once you have set up the relationship and created some records, you can start using the related records for a particular model. In our example, we can use categories method to get the related categories for a product and similarly we can use products to get all products for a given category.

$category = Category::find(1);
$category->products; // will return all products for the category id 1

$product = Product::find(1);
$product->categories; // will return all categories for the product id 1

As many to many relationship always return the collection, you can run the loop on it to render your records.

Deleting a Many To Many Relationship

The way we have used the attach() method to attach many to many models, we can use detach() to remove the many to many relationship between models.

$category = Category::find(2);
$product = Product::find(1);

$product->categories()->detach($category);

Now head over to your category_product table and you will see that category_id 2 record has been deleted from the table.

Detaching Records
Detaching Records

Conclusion

In this tutorial, we looked at how we can use the Many to Many relationships in Laravel Eloquent. I will recommend you to spend some good time on reading Laravel Official Documentation.

If you have any question about this post, leave them in the comments box below and we will reply promptly.

Your little help will keep this site alive and help us to produce quality content for you.