Laravel Eloquent Relationships: The Complete Guide

8
304
Laravel Eloquent Relationships

Eloquent makes managing and working with these relationships smooth and supports several different types of relationships:

If you want to learn more about Laravel, check out the following link.

Laravel Eloquent Relationships

Eloquent relationships in Laravel are defined as the methods on your Eloquent model classes. It is like Eloquent models themselves; relationships also serve as an essential query builder, representing the relationships as methods provide powerful method chaining and querying capabilities.

Step 1: Configure Laravel Project

Install by the following command.

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

Set up the  MySQL database.

Now, edit the .env file.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=relationship
DB_USERNAME=root
DB_PASSWORD=mysql

Now, we need to make Three tables to build the relationships between them.

  1. Orders table
  2. Items table
  3. Invoice table
php artisan make:migration create_items_table
php artisan make:migration create_orders_table
php artisan make:migration create_invoice_table

Define the Schema of these tables.

<?php

// create_items_table

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

class CreateItemsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('items', function (Blueprint $table) {
            $table->increments('id');
            $table->string('item_name');
            $table->integer('price');
            $table->timestamps();
        });
    }

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

// create_orders_table

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

class CreateOrdersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id');
            $table->integer('item_id');
            $table->timestamps();
        });
    }

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

// create_invoice_table

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

class CreateInvoiceTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('invoice', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id');
            $table->integer('order_id');
            $table->integer('paid_amount');
            $table->timestamps();
        });
    }

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

Next, type the following command.

php artisan migrate

It will create all five tables in the database.

Step 2: Fill the dummy data into the database.

Type the following command to generate the seed files.

php artisan make:seeder UsersTableSeeder
php artisan make:seeder ItemsTableSeeder
php artisan make:seeder OrdersTableSeeder
php artisan make:seeder InvoiceTableSeeder

Feed these tables with the values.

<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
         DB::table('users')->insert([
            'name' => str_random(10),
            'email' => str_random(10).'@gmail.com',
            'password' => bcrypt('secret'),
        ]);
          DB::table('users')->insert([
            'name' => str_random(10),
            'email' => str_random(10).'@gmail.com',
            'password' => bcrypt('secret'),
        ]);
           DB::table('users')->insert([
            'name' => str_random(10),
            'email' => str_random(10).'@gmail.com',
            'password' => bcrypt('secret'),
        ]);
            DB::table('users')->insert([
            'name' => str_random(10),
            'email' => str_random(10).'@gmail.com',
            'password' => bcrypt('secret'),
        ]);
             DB::table('users')->insert([
            'name' => str_random(10),
            'email' => str_random(10).'@gmail.com',
            'password' => bcrypt('secret'),
        ]);
    }
}
<?php

use Illuminate\Database\Seeder;

class ItemsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('items')->insert([
            'item_name' => 'mobile',
            'price' => 1000
        ]);
         DB::table('items')->insert([
            'item_name' => 'laptop',
            'price' => 2000
        ]);
          DB::table('items')->insert([
            'item_name' => 'camera',
            'price' => 500
        ]);
           DB::table('items')->insert([
            'item_name' => 'ipod',
            'price' => 200
        ]);
            DB::table('items')->insert([
            'item_name' => 'tabs',
            'price' => 800
        ]);
    }
}
<?php

use Illuminate\Database\Seeder;

class InvoiceTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('invoice')->insert([
            'user_id' => 1,
            'order_id' => 1,
            'paid_amount' => 1000
        ]);
         DB::table('invoice')->insert([
            'user_id' => 3,
            'order_id' => 2,
            'paid_amount' => 4000
        ]);
          DB::table('invoice')->insert([
            'user_id' => 4,
            'order_id' => 4,
            'paid_amount' => 1000
        ]);
           DB::table('invoice')->insert([
            'user_id' => 5,
            'order_id' => 5,
            'paid_amount' => 1000
        ]);
            DB::table('invoice')->insert([
            'user_id' => 2,
            'order_id' => 3,
            'paid_amount' => 1000
        ]);
    }
}
<?php

use Illuminate\Database\Seeder;

class OrdersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('orders')->insert([
            'user_id' => 1,
            'item_id' => 1
        ]);
        DB::table('orders')->insert([
            'user_id' => 1,
            'item_id' => 5
        ]);
        DB::table('orders')->insert([
            'user_id' => 2,
            'item_id' => 2
        ]);
        DB::table('orders')->insert([
            'user_id' => 4,
            'item_id' => 3
        ]);
        DB::table('orders')->insert([
            'user_id' => 5,
            'item_id' => 1
        ]);
    }
}

Now, finally, call all these classes in the DatabaseSeeder.php file.

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UsersTableSeeder::class);
        $this->call(OrdersTableSeeder::class);
        $this->call(ItemsTableSeeder::class);
        $this->call(InvoiceTableSeeder::class);
    }
}

So, it fills the values described in the query.

Step 3: Make models for all these three new tables.

Type the following command.

php artisan make:model Item
php artisan make:model Order
php artisan make:model Invoice

One To Many Relationships

A “one-to-many” relationship is generally used to define relationships where a single or one model owns any other model.

In our example, the User can have multiple Orders.

So, in the User model, we can write the following functions.

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    public function orders(){
        return $this->hasMany(Order::class);
    }
}

Now, go to the terminal and type the following command.

php artisan tinker

Type the following code in it.

$orders = App\User::find(1)->orders;

So, it will display the orders whose user_id is 1

Illuminate\Database\Eloquent\Collection {#734
     all: [
       App\Order {#738
         id: 1,
         user_id: 1,
         item_id: 1,
         created_at: null,
         updated_at: null,
       },
       App\Order {#741
         id: 2,
         user_id: 1,
         item_id: 5,
         created_at: null,
         updated_at: null,
       },
     ],
   }

If your table’s local Primary Key is different, id and Foreign Key are different from user_id. Then, you need to specify further arguments like this.

<?php

public function orders()
{
  return $this->hasMany('App\Order', 'foreign_key', 'local_key');
}

One To Many (Inverse)

Now that we can access the user that has placed the order.

So, in the Order.php model, put the following function in it.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    /**
     * Get the user that owns an order.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Go to the tinker and type the following code in it.

 $user = App\Order::find(2)->user;

It will list the output like the following.

App\User {#735
 id: 1,
 name: "kbXBRnz9no",
 email: "9WQ1CwXjZY@gmail.com",
 created_at: null,
 updated_at: null,
 }

So, we can find the User that had placed the Order.

Finally, our First article on One to Many Relationships is over.

Another relationship tutorial will publish in the next article.

If you have any questions regarding Laravel Eloquent Relationships, ask in a comment below.

8 Comments

    • Hi Dan,

      Its true that the first time tinker will work in this example and give you the required 2 entries. However, if you try the second example “`$user = App\Order::find(2)->user;“` it will return null. The reason is that at this stage tinker doesn’t know the second method (belongsTo) that you just created. The solution if for you to exit tinker and rerun it. This will work. It’s like a refresh… Lol

  1. Hi, first i run the command tinker, i found the error message like this :

    PHP Notice: Trying to get property ‘orders’ of non-object in Psy Shell code on line 1

    • I ran into the same problem. I think that’s because the seeding wasn’t performed yet (it’s is not described here). After some searching I found the following article: https://laravel.com/docs/5.7/seeding

      composer dump-autoload
      php artisan db:seed

      This seeded the tables, so now I didn’t get that messages.

Leave A Reply

Please enter your comment!
Please enter your name here

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