2

Knowing the structure below, can I add a function to the Container class to get records directly with Container::with('records')->get() instead of Container::with('boxes.letter.records')->get() ?

containers hasMany boxes hasOne letter hasMany records

class Container extends Model
{
    public function boxes(): hasMany
    {
        return $this->hasMany(Box::class);
    }
    public function letters(): hasManyThrough
    {
        return $this->hasManyThrough(Letter::class, Box::class);
    }
}
class Box extends Model
{
    public function letter(): hasOne
    {
        return $this->hasOne(Letter::class);
    }
}
class Letter extends Model
{
    public function records(): hasMany
    {
        return $this->hasMany(Record::class);
    }
}
DevonDahon
  • 7,460
  • 6
  • 69
  • 114

2 Answers2

0

Yes, you can indeed create a hasManyThrough relationship from Container to Record by chaining the relationships like this:

class Container extends Model
{
    // Existing relationships...

    public function records(): HasManyThrough
    {
        return $this->hasManyThrough(Record::class, Letter::class, 'box_id', 'letter_id');
    }
}

But make sure you should have proper foreign keys defined in database tables.

dekts
  • 744
  • 4
  • 19
  • 2
    The Box model seems missing from this function, is it unnecessary? – DevonDahon Jul 27 '23 at 13:55
  • Yes, you are right, the relationship chain should go from Container to Box to Letter, and then from Letter to Record. check updated code. – dekts Jul 28 '23 at 05:27
0

Solution # 1 (hasManyThrough with joins)

Yes, you can access the records of a 3rd table directly through the use of hasManyThrough, however need use joins to will can connect more tables.

class Container extends Model
{
    public function records(): hasManyThrough
    {
        return $this->hasManyThrough(Box::class, Letter::class)
                    ->join('records', 'letters.id', '=', 'records.letter_id')
                    ->select('records.*');
    }
}

Solution # 2 (hasManyDeep by package)

Package: staudenmeir/eloquent-has-many-deep

However, this allows you to quickly handle this multi-table relationship. With hasManyDeep, you can define complex relationships across multiple tables with ease.

class Container extends Model
{
    public function records(): hasManyDeep
    {
        return $this->hasManyDeep(Record::class, [Box::class, Letter::class]);
    }
}

About hasManyDeep from Laravel News

rozsazoltan
  • 2,831
  • 2
  • 7
  • 20