Has one through Laravel Eloquent

This is relevant to your original inquiry.

hasOneThrough will be available in Laravel 5.8

https://github.com/laravel/framework/pull/26057/files


It looks like you are not relating objects correctly. Let's break that down:

If a Garage Has Many Car then a Car Belongs To Garage, Lets proceed with this idea in mind.

  • Garage Has Many Car
  • Car Has Many Security
  • Security Belongs To Car
  • Garage Has Many Security Through Car

In Eloquent you can just go ahead and clap those relations in, it should work given the schema you posted above.

class Garage extends Eloquent
{
    public function cars()
    {
        return $this->hasMany('cars');
    }

    public function securities()
    {
        return $this->hasManyThrough('Security', 'Car');
    }
}

class Car extends Eloquent
{
    public function securities()
    {
        return $this->hasMany('Security');
    }

    // ADDED IN SECOND EDIT

    public function garage()
    {
        return $this->belongsTo('Garage');
    }       
}

class Security extends Eloquent
{
    public function car()
    {
        return $this->belongsTo('Car');
    }
}

And that should be it.

EDIT: You can access all these relations from any model as long as there is a path you can draw from one model to another using a combination of these relations. Check this out for example:

$security = Security::with('car.garage')->first();

will retrieve first Security record and load Car relation on it, then it goes one more step and load all Garage relations on every Car object loaded under Security model.

You can access them using this syntax:

$security->car->garage->id

// Other examples
$garage = Garage::with('cars.securities')->first();

foreach($garage->cars as $car)
{
    foreach($cars->securities as $security)
    {
        echo "Car {$car->id} has {$security->id} assigned to it";
    }
}

Furthermore, notice that the relationship objects are an instance of Collection so you have all the fancy methods such as ->each(), ->count(), ->map() available on them.


I ran into a similar problem recently and was able to do something like this:

class Cars extends Eloquent
{
    public function garage()
    {
        return $this->hasOne('Garages');
    }
}

class Securities extends Eloquent
{
    public function car()
    {
        return $this->hasOne('Cars');
    }

    public function garage()
    {
        return $this->car->garage();
    }
}

This gives you the Securities has one garage relationship and you can do something like:

$securities = Securities::with('garage')->get();

foreach($securities as $security)
{
    echo $security->security_name . ' is on ' . $security->garage->garage_name;
}