laravel / cashier-stripe

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.
https://laravel.com/docs/billing
MIT License
2.38k stars 677 forks source link

Bug: "The attribute [stripe_id] either does not exist or was not retrieved for model [App\Models\User]" #1705

Closed devajmeireles closed 2 months ago

devajmeireles commented 2 months ago

Cashier Stripe Version

15.4.1

Laravel Version

11.20.0

PHP Version

8.3.10

Database Driver & Version

MySQL 8.0.36

Description

I have a basic test checking whether the logout occurs successfully in the application:

it('should be able to logout', function () {
    $user = User::factory()->create();

    test()->actingAs($user);

    $this->assertAuthenticatedAs($user);

    $this->get(route('logout'))
        ->assertSessionHasNoErrors()
        ->assertRedirect(route('login'));

    $this->assertGuest();
});

Along with the application, I also have an observer linked to the User model:

#[ObservedBy(UserObserver::class)]
class User extends Authenticatable
{
    use Billable;
    use HasFactory;
    use Notifiable;

    // ...
}
class UserObserver
{
    public function updated(User $user): void
    {
        if (!$user->hasStripeId()) {
            return;
        }

        dispatch(fn () => $user->syncStripeCustomerDetails());
    }
}

When I run the test, I get an error because stripe_id does not exist as a property defined anywhere in the model:

CleanShot 2024-08-14 at 23 41 05

Steps To Reproduce

  1. Replicate the description given above without setting stripe_id as a property.
devajmeireles commented 2 months ago

Fix: #1706

crynobone commented 2 months ago

stripe_id should be accessed via Model attribute. Probably best to include failing tests for this use case.

crynobone commented 2 months ago

This can be solved by:

  1. Adding default stripe_id value to null on UserFactory class.
  2. Refresh the $user after $user = User::factory()->create(); to avoid using actingAs() removing $user->wasRecentlyCreated to false and causing MissingAttributeException with strict eloquent setup.
crynobone commented 2 months ago

See https://github.com/laravel/cashier-stripe/pull/1706#issuecomment-2291877484