'Laravel eager loading with() not working with custom columns

I have the following relationship in my Component model:

public function subComponent()
{
    return $this->belongsTo(SubComponent::class, 'code', 'code');
}

Both have a column called code with data type string. One example for a code would simply be "AB1234".

I try to load components together with their sub components based on this code:

Component::with('subComponent')->get();

Now a few records are not loaded with their resceptive component for some reason. The interesting part is that is is working if I do not eager load it:

Component::where('code', 'ABC1234')->first()->subComponent;

But this only happens to specific sub components. Most of them can be eager loaded and I cannot find a reason why others are not loaded. I have activated https://github.com/barryvdh/laravel-debugbar to investigate what happens in the background but it seems absolutely correct:

select * from `components` where `code` = 'ABC1234' limit 1;
select * from `sub_components` where `sub_components`.`code` in ('ABC1234');

If I execute the second statement it is giving me the proper result. But it is not applied to the component collection. This behaviour does not apply to all components. Most of them do eager load their sub component. But some others have this described odd behaviour. I cannot find the reason why.



Solution 1:[1]

I think the problem is due to your relation declaration.
When you declare this :

public function subComponent()
{
    return $this->belongsTo(SubComponent::class, 'code', 'code');
}

It means that your Component belongTo a subComponent. I think it is the opposite. You should redeclare your subComponent relation like this :

  1. If Component --HasOne--> SubComponent
public function subComponent()
{
    return $this->hasOne(SubComponent::class, 'code', 'code');
}
  1. If Component --HasMany--> SubComponent
public function subComponent()
{
    return $this->hasMany(SubComponent::class, 'code', 'code');
}

This fix should solve your problem.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Théo Champion