TomasVotruba / bladestan

PHPStan analysis for Blade templates
https://tomasvotruba.com/blog/introducing-bladestan-phpstan-analysis-of-blade-templates/
MIT License
280 stars 13 forks source link

Cannot access property error via `auth()->user()` when property is always available #97

Closed johnbacon closed 3 months ago

johnbacon commented 3 months ago

We're seeing the following errors in a Blade template:

  23     Cannot access property $ID on App\Models\Account|null.                                                                                
         rendered in: test.blade.php:99                                                                                                        
  23     Cannot access property $ID on App\Models\EventPlanner|null.                                                                           
         rendered in: test.blade.php:105                                                                                                       
  23     Cannot access property $ID on App\Models\Promokit|null.                                                                               
         rendered in: test.blade.php:103         

Here is how they are being output in the template:

@auth('account')
    (<code>{{ auth('account')->user()->id }}</code>)
@endauth
@auth('promokit')
    <p>Active PromoKit: <code>{{ auth('promokit')->user()->id }}</code></p>
@elseauth('event-planner')
    <p>Active event planner: <code>{{ auth('event-planner')->user()->id }}</code></p>
@endauth

In both cases, the ->id column is non-nullable in the database schema, which we're utilizing via PHPStan with the following config option:

    squashedMigrationsPath:
        - database/schema

In the examples above, there is an outer @auth directive conditional, but note that it occurs even without those. It also occurs with fields other than ->id. And although we have multiple guards, it also occurs with auth()->user()->id (which utilizes the default guard, which is account).

Why is this the case? Is it an issue with Bladestan or are we doing something incorrectly?

Thank you!! We'd love to use your great extension.

AJenbo commented 3 months ago

The problem is that auth()->user() can return either the user og null if no one is authenticated. It isn't aware that you might have already made sure that it's not possible to get to this portion of the code with out being authenticated.

You basically have to wrap this in a helper that will throw an error if the result is null, so that you can guaranty that the function will only ever return a user.

function authUser(): \Illuminate\Contracts\Auth\Authenticatable {
    $authed =  auth()->user();
    if ($authed === null) {
        abort(403);
    }
    return $authed;
}
johnbacon commented 3 months ago

Thank you for the explanation. Maybe my thread will help someone in the future. 🖖