Andre F.
Andre F.

Reputation: 1163

Laravel 5.3 Eloquently Lazy/Eager load multiple models while selecting certain columns

Description:

Hello, in my scenario I'm trying to perform joins on 3 tables regarding a connections system I've built up. I'm able to use eloquent to connect these 3 tables together correctly and return the results no problem however, I'm trying to be more efficient in how it's done. I don't enjoy the fact that every query eloquent fires off defaults to a select * so I'd like to select specific columns instead. Here's where I'm currently at:

Connection Controller Code

 Groups::with([
      'list.userAccount.profile'
 ])->where('user_id_fk', $my->user_id)
    ->orderBy('group_num', 'ASC')
    ->take(3)
    ->get(['group_num','group_title','group_id']);

Group Settings Model

 public function list() {
    return $this->hasMany('App\UserConnections','group_id_fk');
 }

User Connections Model

public function userAccount() {
    return $this->hasOne('App\User','user_id_fk');
}

User Account Model

public function profile() {
    return $this->hasOne('App\Profile','user_id_fk');
}

Now, If I make a call to it's assigned route to get users an example result is the following:

{
"conn_id_fk": 2,
"user_id_fk": 10,
"type": 0,
"group_id_fk": 4,
"status": 1,
"created_at": "2017-02-09 13:58:34",
"updated_at": "2017-02-09 13:58:34",
"user_account": {
  "user_id": 10,
  "email": "[email protected]",
  "verified": 0,
  "locked": 0,
  "code": 0,
  "request": "",
  "created_at": "2017-02-09 13:20:51",
  "updated_at": "2017-02-09 13:20:51",
  "profile": {
    "user_id_fk": 3,
    "first_name": "Jillian",
    "last_name": "Jacobs",
    "avatar": "",
    "age": 0,
    "about_me": "",
    "one_liner": "",
    "inspire": "",
    "created_at": "2017-02-09 13:18:32",
    "updated_at": "2017-02-09 13:18:32"
  }
}

Again My dilemma is that I don't want it to do select * to get all that data, it's unnecessary and will eventually slow down my server and cost me more money on I/O alone.

I've tried doing something like the following for example:

public function profileEnd() {
    return $this->hasOne('App\Profile','user_id_fk');
}

public function profile() {
    return $this->profileEnd->select('first_name','last_name','avatar');
}

///////////////////// AND I have tried///////////////////////////

public function profileEnd() {
    return $this->hasOne('App\Profile','user_id_fk');
}

public function profile() {
    return $this->profileEnd->select(['first_name','last_name','avatar'])->get(); <---Returns 500
}

which results in the following:

{
"conn_id_fk": 2,
"user_id_fk": 10,
"type": 0,
"group_id_fk": 4,
"status": 1,
"created_at": "2017-02-09 13:58:34",
"updated_at": "2017-02-09 13:58:34",
"user_account": {
  "user_id": 10,
  "email": "[email protected]",
  "verified": 0,
  "locked": 0,
  "code": 0,
  "request": "",
  "created_at": "2017-02-09 13:20:51",
  "updated_at": "2017-02-09 13:20:51",
  "profile": null   <------------------------------- Kills off the profile section
}

So What am I doing wrong here and how can I fix this? Any assistance is greatly appreciated. Thanks in advance Cheers!

Upvotes: 1

Views: 139

Answers (1)

patricus
patricus

Reputation: 62248

Laravel needs the keys in order to match up the related collections of models. In your example, you did not select the key, so after the records are retrieved, Laravel has no idea which profiles are related to which user accounts. Add the key to the select and you should be good to go.

public function profileEnd() {
    return $this->hasOne('App\Profile', 'user_id_fk');
}

public function profile() {
    return $this->profileEnd->select('user_id_fk', 'first_name', 'last_name', 'avatar');
}

Upvotes: 1

Related Questions