Erich
Erich

Reputation: 2616

Laravel belongsTo relationship returns null

I'm building a rudimentary CRM app using Laravel 6.0. Users can freely create accounts, but to get any functionality out of the app, they need to set up a SubscriptionAccount (or join an existing one), which will then allow them to create/manage customer Accounts, add Users, etc. (each is a one to many).

The User model's relationship to SubscriptionAccount model is giving me issues. For example:

$user = User::find(1);
$user->subscription()->create(['name' => 'Test Subscription']);
$user = $user->fresh();
dd($user->subscription); // returns null

I suspected it had to do with the belongsTo relationship in the User model, but the odd thing is that it actually creates and persists a new SubscriptionAccount while using that relationship (second line above), though if you access users relationship from the new SubscriptionAccount it also returns null.

Here are the models:

// User.php
class User
{
    public function subscription()
    {
        return $this->belongsTo(SubscriptionAccount::class, 'subscription_account_id');
    }
}

// SubscriptionAccount.php
class SubscriptionAccount extends Model
{
    public function users()
    {
        return $this->hasMany(User::class, 'subscription_account_id');
    }
}

The only thing out of the ordinary is shortening the name of the relationship to subscription from SubscriptionAccount, but that should have been taken care of by specifying the foreign key in both relationships. Here's the migrations:

Schema::create('subscription_accounts', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->uuid('uuid')->unique();
    $table->string('name');
    $table->timestamps();
});

Schema::create('users', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->uuid('uuid')->unique();
    $table->bigInteger('subscription_account_id')->unsigned()->index()->nullable();
    $table->string('name');
    ...
    $table->timestamps();
    $table->foreign('subscription_account_id')
        ->references('id')
        ->on('subscription_accounts');
});

If I create the user from a SubscriptionAccount (i.e. $subscriptionAccount->users()->create([...]); it sets the correct subscription_account_id on the users table, but doesn't work vice versa.

Upvotes: 0

Views: 2070

Answers (2)

newUserName02
newUserName02

Reputation: 1678

This is a known issue (feature?) with the belongsTo relationship:

https://github.com/laravel/framework/issues/29978

To work around it you can associate the models manually:

$user = User::find(1);
$sub = Subscription::create(['name' => 'Test Subscription']);
$user->subscription()->associate($sub);
$user->save();

Upvotes: 2

nakov
nakov

Reputation: 14248

So instead of using belongsTo because a subscription account does not belongs to one user, it can belong to many, you might want to use the hasOne relationship instead:

public function subscription()
{
    return $this->hasOne(SubscriptionAccount::class, 'id', 'subscription_account_id');
}

It will belongTo one User if you had a user_id within the subscription_accounts table.

Let me know if it makes sense and if it works :)

Upvotes: 0

Related Questions