Introducing One To Many Relationship in Laravel

Introducing One To Many Relationship in Laravel

In this post, we will look at how we can create one to many relationships in Laravel with an example.

What is One To Many Relationship?

One To Many relationship also known as hasMany relationship links one row in the database table to many rows in other database tables. This relationship type is mostly used while Laravel application development due to its use case.

In Laravel Eloquent, one model can owns multiple models which is one to many link. For example, in a ecommerce application scenario a Brand model can have many Product model and a Product model belongs to a Brand model. This relationship is depicted in the below diagram.

One To Many Relationship
One To Many Relationship

One To Many relationship is very simple as One To One relationship, which we covered in the last post Introducing One To One Relationship in Laravel. To understand One To Many relationship and how we can use it, we will look at a very simple yet real example.

Creating Models and Migrations

To implement one to many realtionship, we will need two tables in our database brands and products.

Note

I assume you have fresh installation of Laravel and have setup the database credentials in .env file.

We will start to create the model and migrations, then we will define the one to many relationship.

To generate models and migrations, run below two commands in your terminal.

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

Above command will generate two models in your app folder called Brand and Product. You will also find two new migrations in your database/migrations folder.

Your newly created models and migration will look like below:

Brand Model:
// Brand Model
namespace App;

use Illuminate\Database\Eloquent\Model;

class Brand extends Model
{
    //
}
Brand Migration:
// Brand Migration
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBrandsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('brands', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('brands');
    }
}
Product Model:
// Product Model
namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    //
}
Product Migration:
// 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->timestamps();
        });
    }

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

Once you have the models and migrations generated, update the up() method of the brand and product migrations with the below one.

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

In the above code example, we have added a few table fields for the brand’s table.

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->integer('brand_id')->unsigned();
        $table->foreign('brand_id')
          ->references('id')->on('brands')
          ->onDelete('cascade');
        $table->string('name');
        $table->string('slug');
        $table->double('price');
        $table->integer('qty');
        $table->text('description');
        $table->timestamps();
    });
}

In the above code example, we have added few table fields for the products table. One thing to pay attention is the brand_id column which is a foreign key on the brands id column.

Now run the below command to create brands and products tables in your database:

php artisan migrate

Defining One To Many Relationship in Laravel

Once we have brands and products tables ready, let’s define the one to many relationship in our models.

Open your app/Brand.php model file and add a new function called products() which will return a hasMany relationship like below:

// Brand Model
namespace App;

use Illuminate\Database\Eloquent\Model;

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

Note

We are returning a one to many relationship for brand model, which will return more than one record of product model, that’s why we have named it products. Later when we will define the inverse one to many relationship on the product model, we will use the singular name like brand. Each product will have one brand that’s why we have to use the singular name.

As you can see, in the products() method we are defining a hasMany relationship on Product model.

Defining Inverse One To Many Relationship in Laravel

As we have defined the hasMany relationship on Brand model which return the related records of Product model, we can define the inverse relationship on the Product model.

Open your app/Product.php model file and add a new method called brand() in it which will return the related brand of a product.

Once you have added a new method brand(), update it with the below code snippet.

// Product Model
namespace App;

use Illuminate\Database\Eloquent\Model;

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

As you can see, in brand() method we are returning a belongs to relation which will return the related brand of the product.

Retrieving One To Many Relationship Data

Once you have defined the relationship on models, we can start using the models to retrieve the related records. In our example, for a particular brand, we can use products() method to get all the related products of a brand.

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

When we try to get products for a brand, Laravel will look into products table with the brand ID in the brand_id columns and grab all the products matching with this ID.

Similarly, we can retrieve the inverse related model.

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

For inverse one to many relationship, Laravel look into brands table with the ID from brand_id column and return the matching record.

Creating a One To Many Relationship

To create a relationship between two models or associating them, we can first create a child object and then save it using the parent object.

$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);

You can also use the saveMany() method instead of save() to associate multiple records.

Filtering One To Many Relationship

You might want to filter the related records and want them to sort when retrieving. You can chain the methods on your retrieving query.

$brand = Brand::find(1);
$products = $brand->products()
			->where('price', '>', '500')
			->orderBy('name', 'asc')
			->get();

In the above query, we are getting all products for a brand where the price of each product should be greater than 500 and sorting the records by name in ascending order.

Deleting a One To Many Relationship

Deleting one to many relationship is the same as we have created them. Firstly we get the parent object which is brand and then use the products() method to delete all products. To delete all products for a particular brand use below code example.

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

Conclusion

I have tried my best to keep this post as simple as possible because Laravel relationships are the most misunderstood part. I will recommend you to spend some good time on reading Laravel Official Relations Documentation.

If you have any question or suggestion, please leave them in the comments box below.

5 comments on “Introducing One To Many Relationship in Laravel

  1. your this article help me a lot even more helpful than laravel official documentation, because you did and show everything practically..

Leave a Reply

Your email address will not be published. Required fields are marked *

*

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.

What's New in Laravel 5.8
Laravel 5 was released in February 2015 and current Laravel 5.7 was released in September 2018. We should be expecting...