chrisgrim's avatar

Relations Not working like expected, looking for troubleshooting techniques

I have setup simple belongsTo HasMany between my Listing.php model and my User Model.

User.php

namespace App\Models;

use App\Models\Curated\Listing;

public function listings() 
    {
        return $this->hasMany(Listing::class);
    }

Listing.php

namespace App\Models\Curated;

use App\Models\User;

/**
     * Get the user that owns the Listing.
     */
    public function owner()
    {
        return $this->belongsTo(User::class);
    }

And in my listing migration

Schema::create('listings', function (Blueprint $table) {
            $table->id();
            $table->string('slug')->unique();
            $table->string('name')->nullable();
            $table->mediumText('blurb')->nullable();
            $table->foreignId('community_id');
            $table->foreignId('user_id');
            $table->string('largeImagePath')->nullable();
            $table->string('thumbImagePath')->nullable();
            $table->char('status', 1)->default('d');
            $table->integer('order')->unsigned()->default(0);
            $table->timestamps();
        });

If I create a listing and then do

return auth()->user()->listings()->get();

I get

"id": 1,
"slug": "badnda-1",
"name": "Badnda",
"blurb": "<h3>xzsxzsx</h3><p></p><p>xzsxzsxzsxzsx</p><p>xzsxzsx</p>",
"community_id": 1,
"user_id": 1,
"largeImagePath": "listing-images/badnda-1-1/badnda-1.webp",
"thumbImagePath": "listing-images/badnda-1-1/badnda-1-thumb.webp",
"status": "p",
"order": 0,
"created_at": "2021-07-02T23:16:58.000000Z",
"updated_at": "2021-07-02T23:16:58.000000Z"

However if I do

return Listing::find(1)->owner()->get();

I get an empty array. How do I start troubleshooting this? I tried doing

return $this->belongsTo('App\Models\User');

but that still returns empty.

0 likes
8 replies
tykus's avatar
tykus
Best Answer
Level 104

Since the relation is owner, but the foreign key is not owner_id. you must specify the foreign key whenever you defined the relationship:

Eloquent determines the foreign key name by examining the name of the relationship method and suffixing the method name with _id. So, in this case, Eloquent assumes that the Phone model has a user_id column. However, if the foreign key on the Phone model is not user_id, you may pass a custom key name as the second argument to the belongsTo method:

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

To get the owner for an instance, you can use the relation as a property; i.e. without the get() method

return Listing::find(1)->owner;
bugsysha's avatar

Noooo, he asked for steps to learn to debug. Why did you give him the solution 🤣

chrisgrim's avatar

@tykus Thank you!!! That worked. Why didn't it work by default though?

tykus's avatar

Eloquent determines the foreign key name by examining the name of the relationship method and suffixing the method name with _id. So, in this case, Eloquent assumes that the Phone model has a user_id column. However, if the foreign key on the Phone model is not user_id, you may pass a custom key name as the second argument to the belongsTo method:

You have owner relationship, but the foreign key is user_id

bugsysha's avatar

You go step by step. First check what the Listing::find(1) returns. Then you can always do Listing::find(1)->owner()->toSql() and see what query is executed and also run that query manually on the database to see if the data matches. Many times I've wasted hours just to realize that I was querying the wrong database (production instead of local).

chrisgrim's avatar

This is amazing! I didn't know about SQL. It returned

select * from `users` where `users`.`id` is null

Where would I have gone from here because it is looking in the right place.

bugsysha's avatar

is null in the query is the key that should give you a hint that the relationship wasn't properly defined. You know there is a correct value in the user_id column and here in the query that is not reflected. So for that reason, you would go and verify your relationship definitions according to the documentation and realize that you were missing user_id because you've named the relationship owner instead of default user. Hope this makes sense.

Please or to participate in this conversation.