Search code examples
laraveleloquentlaravel-relations

Laravel Model Relations fetch automatically all other model relations too


I'm hoping someone can help me.

I have 3 models like User, Task and Subtask. These are already linked via hasOne or hasMany. Everything works fine. Now I call the data via Task::where(..)->with(['user','subtask'])... and get the corresponding results.

The problem is that Subtask has a reference to User and I don't get the user information queried when I use the task model.

If I use the subtask model I get the user information.

How can I set up that all references to the queried models are also queried simultaneously from the database?


Solution

  • To return more relationships data at once, you can use the following mechanism:

    $Data = $Task::where(...)
        ->with([
            'user'=>function($userQuery){
                // mechanism is recursive; you can extend it to infinity :)
                $userQuery->with([
                                'other', 
                                'relationships', 
                                'here'=>function($hereQuery){ ... } 
                            ]); 
            },
    
            'subTask',
    
            'anotherRelationship' => function($anotherRelationship) {
                $anotherRelationship->select('column');
                $anotherRelationship->where('column2', 'whatever');
            }
        ])
        ->get();
    
    // dump data
    dd($Data);
    

    I don't know if you're looking for this -- if you want to load some relationships once the model is instantiated, you can append a magic variable $with inside your model code and specify which relationships you want to load:

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Task extends Model
    {
        protected $fillable = ['col1', 'col2', 'col3', ...];
    
        // specify which relationships you want to load automatically
        protected $with = [
            'users',
            'anotherRelationship'=>function($anotherRelationshipQuery){
                $anotherRelationshipQuery->select( ... );
            },
            'andSomeOtherRelationship'
    
            ...
        ];
    
        ...
    }
    

    Now you no longer need to manually load the relationships when retrieving data. They're loaded automatically:

    $Data = $Tast::where( ... )->get();
    
    dd($Data);