Happy Coder
Happy Coder

Reputation: 4682

Laravel hasOneThrough relationship returns null

I have the following table structure in MySQL database:

Products
    id - integer
    name - string
    user_id -string

Users
    user_id - string
    password - string
    person_id - integer

Persons
    person_id - integer
    name - string
    email - integer

I am using hasOneThrough relationship on Products model to get the details about the Person, who is linked through Users. The code that defines the relation is as follows :

public function product_user()
{
    return $this->hasOneThrough(
        'App\Person',
        'App\User',
        'person_id',
        'person_id',
        'user_id',
        'user_id'
     );
}

But I am getting null when I try to access the property product_user, it is giving me null all the time. I cannot change the database structure. How can I define a proper relationship in this scenario ?

Upvotes: 1

Views: 1538

Answers (1)

Kurt Friars
Kurt Friars

Reputation: 3764

I always find the documentation for customized relationships a little bit lacking. I will expand on HasOneThrough here:

Lets say A has one C through B.

This relationship means the following would be our schema:

model_a
|  a_id    |    name    |
model_b
|  b_id    | model_a_id |    name   |
model_c
|  c_id    | model_b_id |    name   |

To write out our relationship explicitly defining the keys:

class ModelA extends Model
{
    ...
    
    public function cModel()
    {
        return $this->hasOneThrough(
            ModelC::class,
            ModelB::class,
            'model_a_id', // Key on B that relates to A
            'model_b_id', // Key on C that relates to B
            'a_id',       // Key on A that relates to B
            'b_id',       // Key on B that relates to C
        );
    }

So for your case, it won't quite work. You would like to have "Products has one Person through User", but you actually have "Product belongs to User which belongs to Person" which means you need this custom package (staudenmeir/belongs-to-through) to add that relationship. You can use it like so:

User.php

public function person()
{
    return $this->belongsTo(Person::class, 'person_id', 'person_id');
}

Products.php

use \Znck\Eloquent\Relations\BelongsToThrough;

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

public function person()
{
    return $this->belongsToThrough(
        Person::class,
        User::class,
        null, // PK on products, null === 'id'
        '',   // The foreign key prefix for the first "through" parent model, in case you need aliasing.
        [
            Person::class => 'person_id',  // PK on persons
            User::class => 'user_id',      // PK on users
        ],
    );
}

Upvotes: 5

Related Questions