Laravel Many-to-Many Relationship: How to implement It
Tags: laravel, eloquent, database, webdev
Published: 2022-09-26 19:17:09

---
title: Laravel Many-to-Many Relationship: How to implement It
published: true
date: 2022-05-08 18:22:43 UTC
tags: laravel,eloquent,database,webdev
canonical_url: https://www.iankumu.com/blog/laravel-many-to-many-relationship/?utm_source=rss&utm_medium=rss&utm_campaign=laravel-many-to-many-relationship
---

![Laravel Many to Many](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/humbl9xytspvy58rtgb9.png)
Many to many relationships occur when **multiple records in a table** have an association with **multiple records in another table**. For example, a many-to-many relationship exists between a store and a region in a system: **A store can serve many regions** and **a region can have many stores serving it**. In this tutorial, you will learn **how to implement Laravel Many-to-Many Relationship**. I am going to use the store-region relationship mentioned earlier   
A many to many relationships involve **three tables** in its ecosystem. The two tables will be for the independent tables which in my case will be the **regions table** and the **stores table**. The third table is what is known as a pivot table. A pivot table is an intermediate table that connects the two independent tables using their foreign keys.

## **How do you implement many to many relationships in Laravel?**

To implement  many to many relationships, we will need to follow these steps

### 1. **Create a Laravel Project**

The first step will be to create a Laravel project. If you already have a project, then you can skip this step

```bash
composer create-project laravel/laravel test-app
```

### 2. **Create a model and migration**

The next step is to create the model and migration files for our project. I will first create a **Region Model** and its migration file

```php
php artisan make:model Regions -m

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

        $table->timestamps();
    });
}

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

The next model is the **Stores mode** l and its migration file

```php
php artisan make:model Stores -m

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

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

### 3. **Create a pivot table**

We then need to create a pivot table that will **connect the two tables; stores and regions tables**. In Laravel, a pivot table is created **by checking the alphabetical order of the two-parent tables**. For example, if we had parent **table “a”** and parent **table “b”** , then the **pivot table would be “a\_b”**. Using the same analogy, I can create my pivot table **“regions\_stores”** table for my case.

```bash
php artisan make:migration create_regions_stores_table
```

I will then add the foreign keys of the parent tables as shown

```php
public function up()
{
    Schema::create('regions_stores', function (Blueprint $table) {
            $table->id();
            $table->unsignedBiginteger('regions_id')->unsigned();
            $table->unsignedBiginteger('stores_id')->unsigned();

            $table->foreign('regions_id')->references('id')
                 ->on('regions')->onDelete('cascade');
            $table->foreign('stores_id')->references('id')
                ->on('stores')->onDelete('cascade');

            $table->timestamps();
    });
}

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

### 4. **Define many to many relationships**

Now that we have our parent and pivot tables ready, we will have to define the Laravel many-to-many relationship in the Parent Models. We will use the **belongsToMany()** function to do so. This function expects a series of parameters such as the **related Model** , **optional table name** , **optional foreign pivot key** , and **optional related pivot** key among others. The **only required parameter** is the **related model**. All others can be prefilled for you if you used the **alphabetical naming conventional**.

I personally like specifying the optional parameters too such as **table name** , ** foreign pivot key** , and **related pivot.** This is because I want to have **full control over my pivot table**. 

I will update the **Stores model** as follows

```php
    public function regions()
    {
        return $this->belongsToMany(Regions::class, 'regions_stores', 'stores_id', 'regions_id');
    }
```

![](https://www.iankumu.com/blog/wp-content/uploads/2022/05/stores-1024x554.webp)
_Stores Model_

I will also update my **Regions Models** as follows

```php
    public function stores()
    {
        return $this->belongsToMany(Stores::class, 'regions_stores', 'regions_id','stores_id');
    }
```

![Laravel many-to-many relationship](https://www.iankumu.com/blog/wp-content/uploads/2022/05/regions-1024x559.webp)
_Regions Model_

### 5. **Using the Many to Many Relationship in our Controller**

Once we have defined our many to many relationships, we can now migrate the database

```bash
php artisan migrate
```

The next step is to use these helper functions to help us assign the many to many relationships to our records.

#### attach() function

This method is used to **create and assign a record** to multiple other records. For example, if I have a store and I want to assign regions where it can serve, I can use this method to do so

```php
    public function store(Request $request)
    {
        $regions = [1, 2, 3];

        $stores = new Stores();
        $stores->name = $request->input('store_name');
        $stores->save();
        $stores->regions()->attach($regions);
    }
```

![Laravel many-to-many relationship](https://www.iankumu.com/blog/wp-content/uploads/2022/05/attach-1-1024x577.webp)
_Assign regions to a store_

#### sync() function

This method can be used to **update many to many relationship** attachments. It **reassigns records to the newly provided assignments**. For example, if I had a store A that serves the following regions; London New York, Toronto, and Nairobi, I would want to update its regions by either adding more, I would use this function

```php
    public function update(Request $request, $id)
    {
        $regions = [4, 5];
        $stores = Stores::find($id);
        $stores->regions()->sync($regions);
    }
```

![Laravel many-to-many relationship](https://www.iankumu.com/blog/wp-content/uploads/2022/05/sync.webp)
_Reassign new regions to a store_

#### detach() function

This method is used to **delete the attachment of a record in** many to many relationships. For example. If I have a store record that wants to close down, I would also want to remove its attachment meaning the regions it serves. I can have **this method run before a delete function in my controller**.

```php
public function destroy($id)
    {
        $stores = Stores::find($id);
        $stores->regions()->detach();

        $stores->delete();
    }
```

![Laravel many-to-many relationship](https://www.iankumu.com/blog/wp-content/uploads/2022/05/detach.webp)
_Remove any attached regions from a store before deleting the store_

You can get more details regarding the functions [here](https://www.amitmerchant.com/attach-detach-sync-laravel/).

### 6. **Retrieving Records**

Now that we have our records in a many to many relationship, how do we retrieve the records? In this part, I am going to show you how I retrieve the records from the pivot table and add them to my JSON responses(if I am creating a Laravel API) or a response(If I am creating a Laravel CRUD application).

#### CRUD Fullstack app(Normal Response)

In this case, I can just load all the records using the function I had created in the Parent model and pass them to the blade templates using the **compact()** helper. The **compact() helper creates an array** from the collection passed to it. I would then use a **for each loop** and loop through the array in the blade template and output the required fields.

```php
 public function index()
    {
        $stores = Stores::with('regions')->get();
        return view('home', compact('stores'));
    }
```

![Laravel many-to-many relationship](https://www.iankumu.com/blog/wp-content/uploads/2022/07/crud-1024x470.png)
_Using compact to pass data to the home blade file_

#### Rest API approach(JSON Response)

For this part, you would **not want to expose** other details such as **created\_at** and **updated\_at** to a **front end client**. As a result, you can use **[Laravel Resources](https://laravel.com/docs/9.x/eloquent-resources)** to format your responses. In my case, I will just return all the records including the region details in the same response.

```php
public function index()
    {
        $stores = Stores::with('regions')->get();
        return response()->json([
            'stores' => $stores
        ], 200);
    }
```

![laravel many to many tutorial](https://www.iankumu.com/blog/wp-content/uploads/2022/07/rest-1024x544.png)
_Sample Response for a Rest API_

This will return a JSON response that resembles the one below

```json
{
  "stores": [
    {
      "id": 2,
      "name": "Store A",
      "created_at": "2022-07-07T08:36:50.000000Z",
      "updated_at": "2022-07-07T08:36:50.000000Z",
      "regions": [
        {
          "id": 1,
          "name": "Region A",
          "created_at": "2022-07-07T12:00:46.000000Z",
          "updated_at": "2022-07-07T12:00:51.000000Z",
          "pivot": {
            "stores_id": 2,
            "region_id": 1
          }
        },
        {
          "id": 2,
          "name": "Region B",
          "created_at": "2022-07-07T12:00:56.000000Z",
          "updated_at": "2022-07-07T12:01:01.000000Z",
          "pivot": {
            "stores_id": 2,
            "region_id": 2
          }
        },
        {
          "id": 3,
          "name": "Region C",
          "created_at": "2022-07-07T12:01:05.000000Z",
          "updated_at": "2022-07-07T12:01:09.000000Z",
          "pivot": {
            "stores_id": 2,
            "region_id": 3
          }
        }
      ]
    }
  ]
}
```

## Conclusion

In this tutorial, you have learnt **when to use many to many relationships** and **how to implement Laravel many-to-many relationship**. I hope this article was helpful in your quest of using many to many relationships and helping create good applications.

If you enjoyed this article, you'd love the [Free Laravel Guide](https://www.iankumu.com/blog/newsletter/) I prepared for you. Be sure to get your guide today.
Thank you for reading.

The post [Laravel Many-to-Many Relationship: How to implement It](https://www.iankumu.com/blog/laravel-many-to-many-relationship/) appeared first on [Ian Kumu's Blog](https://www.iankumu.com/blog).