CEJ
CEJ

Reputation: 181

How to get foreign key name of loaded relationship using laravel eloquent

So I currently have 3 models Specie Type User. I want to be able to get the name of the last modified user in relation to the Specie model

The relationships are as follows

Class Specie extends Model {
   public function type()
   {
        return $this->belongsTo('App\Type', 'type_id');
   }

   public function user()
   {
        return $this->belongsTo('App\User', 'user_id');
   }
}

Class Type extends Model {
   public function specie()
   {
        return $this->hasMany('App\Specie', 'type_id');
   }
}

Class User extends Model {
   public function specie()
   {
        return $this->hasMany('App\Specie', 'user_id');
   }
}

I have tried this

Class Specie extends Model {
    public function lastModified()
    {
        return $this->belongsTo('App\User', 'last_modified_by');
    }
}

And then used the below code

$this->type->with(['specie.lastModified' => function ($query) use 
        ($userId) {
            $query->where('user_id', $userId);
        }])->get();

Unfortunately this does not seem to work

However, by using this code

$this->type->with(['specie' => function ($query) use ($userId) {
            $query->where('user_id', $userId);
        }])->get();

I am able to get this:

"id": 1,
"type": "Halo",
"created_at": "2019-07-20 13:02:53",
"updated_at": "2019-07-20 13:02:53",
"specie": [
  {
    "id": 5,
    "user_id": 1,
    "type_id": 1,
    "note": "et",
    "created_by": 1,
    "last_modified_by": 1,
  }
]

However, what I want to get is the name of the last modified person name which is the primary key in the User model and the foreign key in the Specie model

This is what I expect to get:

"id": 1,
"type": "Halo",
"created_at": "2019-07-20 13:02:53",
"updated_at": "2019-07-20 13:02:53",
"specie": [
  {
    "id": 5,
    "user_id": 1,
    "type_id": 1,
    "note": "et",
    "created_by": 1,
    "last_modified_by": 1,
    "last_modified_name": 'gerrard'
  }
]

Upvotes: 0

Views: 4369

Answers (2)

Andrew
Andrew

Reputation: 1150

I used the getKeyName() method on the related model.

My relationship was a one to many so returned as a Collection. Accessing the returned collections first item in collection [0] and then running the getKeyName() worked.

Below my code first checks if the relation data is filled and that its returned as a Collection (multiple) and that there is atleast 1 item.

if(
$item->relatives 
&& $item->relatives instanceof \Illuminate\Database\Eloquent\Collection 
&& count($item->relatives)
) {

     $relation_key = $item->relatives[0]->getKeyName();
}

I presume you could test if relation is return as a Collection of Models or a single Model is returned.

If a single model is returned you can just: $item->relative->getKeyName();

Upvotes: 0

Udochukwu Enwerem
Udochukwu Enwerem

Reputation: 2823

From your Eloquent entity relationships:

Specie and Type(type) are related (one-to-many)

Specie and User(user) are related (one-to-many)

Specie and User(lastModified) are related (one-to-many)

User and Type are not related

So, for you to include the user name you have to query the Specie model through the lastModified() method.

$this->lastModified()->with(['specie' => function ($query) use ($userId) {
            $query->where('user_id', $userId);
        }])->get();

You should expect a result like this

"id": 1,
"name": "the_user_name" 
// any other user data
"created_at": "2019-07-20 13:02:53",
"updated_at": "2019-07-20 13:02:53",
"specie": [
  {
    "id": 5,
    "user_id": 1,
    "type_id": 1,
    "note": "et",
    "created_by": 1,
    "last_modified_by": 1,
  }
]

From the result, the field(foreign key) last_modified_by in specie with value 1 should match the field id in user.

Also, I'm assuming the field for your user name is name. It would be included with the returned user data.

UPDATE

You can not get any user data from the User table through the Type table using eager loading except they are related. Ergo, models must be related (i.e. constrained by each other) before they can be nested, for instance using eager loading. See this medium article to better understand this.

Upvotes: 1

Related Questions