Laravel has one through Eloquent relationship tutorial

Laravel provides eloquent relationship which provides powerful query builders. In Laravel, eloquent relationships are defined in model classes. Laravel eloquent provides easy ways to create common relationships:

We have discussed one-to-one relationship between two models, we can retrieve related record of the specific model using eloquent query. But sometimes, we have situation where two models are having relationship using through third model.

Let's take an example. A Passenger model has one Vehicle model and Vehicle model has Driver model and you want to get Driver of the specific Passenger model. In this relatioship, Passenger model and Driver model doesn't have direct relationship. They are connected through Vehicle model.

Example:

In this example, we assume that you have created fresh Laravel application. We also assume that you have confiured database connection.

Database tables

In this relationship, we have three database tables: passengers, vehicles and drivers. Let's create migration for these database tables.

Migration

we need to create three migration files. Run the following three commands into Terminal to create migration classes at database/migrations directory.

php artisan make:migration create_passengers_table
php artisan make:migration create_vehicles_table
php artisan make:migration create_drivers_table

Below are the migration table fields for these table:

passengers migration

In the posts migration, we have defined the following fields:

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

vehicles migration

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('vehicles', function (Blueprint $table) {
        $table->id();
        $table->integer('passenger_id');
        $table->string('number');
        $table->timestamps();
    });
}

drivers migration

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

Now run the migrate command to create tables into database.

php artisan migrate

Model

Laravel model located at app/Models directory. Create model classes for these tables using following Artisan commands one by one into Terminal.

php artisan make:model Passenger
php artisan make:model Vehicle
php artisan make:model Driver

Now, let's look at the migration fields. We have passenger_id field in the vehicles table and vehicle_id in the drivers field. There is no direct relationship between passengers and drivers table. To define relationship between passengers and drivers table, create a method into Passenger model.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Passenger extends Model
{
    use HasFactory;

    /**
     * Get the driver of vehicle.
     */
    public function vehicleDriver()
    {
        return $this->hasOneThrough(Driver::class, Vehicle::class);
    }
}

In the hasOneThrough method, first argument is the model that we want to access, the second argument is the intermediate model. Of course, you may define custom table fields instead of id of model name field.

/**
 * Get the driver of vehicle.
 */
public function vehicleDriver()
{
    return $this->hasOneThrough(
        Driver::class,
        Vehicle::class,
        'passenger_id', // Foreign key on the vehicles table
        'vehicle_id', // Foreign key on the drivers table
        'id', // Local key on the vehicles table
        'id' // Local key on the drivers table
    );
}

Route

In routes/web.php file, we have added new route for relationship testing.

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\DriverController;

Route::get('/driver', [DriverController::class, 'index']);

Controller

As we have added route, also create DriverController with following command.

php artisan make:controller DriverController

Open the controller at app/Http/Controllers/DriverController and create index method. To retrieve the driver record for the passenger, access vehicleDriver attribute of Passenger model which we have created method.

/**
 * Display a listing of the resource.
 *
 * @return \Illuminate\Http\Response
 */
public function index()
{
    $driver = Passenger::find(1)->vehicleDriver;

    dd($driver);
}

This will return driver record with the associated passenger_id of 1. If the relationship not found, the eloquent will return null record.

I hope this will help you to understand has one through eloquent relationship.

Was this article helpful?

0 out of 0 person found this article helpful.

Leave a comment

Or

No Comment