How to return a collection of models with selected columns and relation eager loaded in Laravel 5.2

时间:2016-04-15 11:13:01

标签: laravel eloquent query-builder eager-loading

Problem details:

I have three models

  • a Directorate with id and name fields,
  • an Employee with id and name fields and
  • a Telephone with id, tel, employee_id, directorate_id, description and type fields. The employee_id may be nullable, that is there are telephones stored in database with employee_id = null

The models are related as follows:

  • an employee may have many telephones
  • a directorate, may have many telephones

    class Directorate extends Model
    {
        public function telephones()
        {
            return $this->hasMany(Telephone::class);
        }
    
        public function employees()
        {
            return $this->hasMany(Employee::class);
        }
    }
    
    
    class Employee extends Model
    {
        public function telephones()
        {
            return $this->hasMany(Telephone::class);
        }
    
        public function directorate()
        {
            return $this->belongTo(Directorate::class);
        }
    }
    
    
    class Telephone extends Model
    {
        public function employee()
        {
            return $this->belongsTo(Employee::class);
        }
    
        public function directorate()
        {
            return $this->belongsTo(Directorate::class);
        }
    }
    

Question:

I want to fetch a Collection of all the Telephone models that belong to a specific Directorate, that have employee_id = null and also having their directorate relation eager loaded. In addition, from that resulting collection of Telephone models, I need only some of the models' fields, that is id, tel and description

Tries

What I tried so far was the following:

I created a query scope in the Telephone model:

public function scopeHaveNoEmployeeId($query)
{
    return $query->where('telephones.employee_id', '=', null);
}

In my controller

$myTelephones = Telephone::with('directorate')

                ->haveNoEmployeeId()

                ->where('directorate_id', $directorateId)

                ->get(['id', 'tel', 'description']);

However what I am receiving are the requested fields of the filtered models without the relation eager loaded, for instance:

[
{
"id": 79,
"tel": "0648136867",
"directorate": null
},
{
"id": 380,
"tel": "0223796011",
"directorate": null
}
] 

I tried also to lazy eager load the relation afterwards but with no luck.

Finally I noticed that if I request all the Telephone models fields, the relation will eager load as I request. For example:

$myTelephones = Telephone::with('directorate')

                ->haveNoEmployeeId()

                ->where('directorate_id', $directorateId)

                ->get();

Then as a result:

[
{
"id": 79,
"tel": "0648136867",
"directorate": {
                "id": 23
                 "name": "Some name"
                }    
},
{
"id": 380,
"tel": "0223796011",
"directorate": {
                "id": 23
                 "name": "Some name"
                }       
}  
] 

2 个答案:

答案 0 :(得分:0)

您的电话与首长级模特没有任何关系。 把它放在你的电话型号中。

public function directorate()
{
    return $this->belongsTo(Directorate::class);
}

答案 1 :(得分:0)

实际上,在深入研究Laravel的细节一段时间之后,我注意到我最初的问题是脱离背景而且有些愚蠢。我是第一次渴望加载一个关系,然后我愚蠢地通过不将它包含在get()参数中来过滤掉这种关系。我只想做以下事情:

$myTelephones = Telephone::with('directorate')

                ->haveNoEmployeeId()

                ->where('directorate_id', $directorateId)

                ->get(['id', 'tel', 'description', 'directorate']);