Home > other >  Nested eager loading dynamically created in a constrain
Nested eager loading dynamically created in a constrain

Time:06-08

songs table

  id  version  number
   1   AAA     1
   2   BBB     1
   3   CCC     1
   4   DDD     2
   5   EEE     3
   6   FFF     4
   7   GGG     4 

The objective is to obtain, for example, all songs that have the same number as the song with id 1 (songs with ids 1, 2 e 3)

Song model

public function songs()
{
    return $this->hasMany(Song::class, 'id_hierarchy');  
}

Query: it doesn't work it's just for demonstration (there is no sameNumber model)

public function readSongsVersions()
{
    $data = Hierarchy::query()
        ->whereNull('parent_id')
        ->with([
            'children.songs'
            'children.songs.sameNumber'
        ])
        ->get();
}

There is no sameNumber model.

Theoretically, a relationship would have to be created in the model song and it would be a relationship with the model song itself; Is such a solution possible?

The solution will eventually go through a constraint.

 $data = Hierarchy::query()
        ->whereNull('parent_id')
        ->with([
            'children.songs'
            'children.songs' => function ($query) {
                    $query->where('number', '=', function($query) {
                        $query->select(DB::raw('i.number)'))
                            ->from('songs as i')
                            ->whereRaw('i.number = songs.number')
                        });
                },
        ])
        ->get();
}

How to nest in eager loading the result of the subquery ( 'children.songs' => function ($query) {...}) to get the sameNumber music collection for each song;

the equivalent of: 'children.songs.sameNumber'

CodePudding user response:

You can create relationships, that references itself. A where statement to ensure, not the same row is returned, since you are relying on the number column.

In Song.php

public function sameNumber()
{
    return $this->hasMany(Song::class, 'number', 'songs.number')
        ->whereColumn('version', '!=', 'songs.version');
}

There is one part you have to figure out, but when you run the code it should be fairly obvious, 'version' and 'number' columns are gonna be ambiguous and you have to check what naming Laravel uses, when dealing with tables named the same. Change the code like so songs2.version, dependent on the naming. You can also always call ->toSql() on the relationships to see the SQL query.

  • Related