I have authentication middleware in my Lumen application like this:
class Authenticate { public function handle(Request $request, Closure $next, string|null $guard = null): mixed { try { /**@var \Illuminate\Auth\RequestGuard $requestGuard*/ $requestGuard = $this->auth->guard($guard); $signedIn = $requestGuard->check(); // ... } catch (NoUserIdProvidedException) { // ... } // ... } } It works fine, but PhpStorm reports that the exceptions (I removed most of them from the example, there are a few) are not thrown by the containing block, although they are.
It seems that deep inside RequestGuard it uses call_user_func
return $this->user = call_user_func( $this->callback, $this->request, $this->getProvider() );
Call the closure set in the AuthServiceProvider, which uses a middleware method on the custom Security class:
class AuthServiceProvider extends ServiceProvider { public function boot(): void { $this->app['auth']->viaRequest('api', function ($request) { $security = new Security(); return $security->middleware($request); }); } } In my opinion, the documentation block for the middleware is correct
/*** @param Request $request * @return bool|object|null * @throws InvalidDomainUser * @throws NoDomainUserException * @throws NoTokenOnRecordException * @throws NoTokenProvidedException * @throws NoUserException * @throws NoUserIdProvidedException*/ public function middleware(Request $request): object|bool|null { Add a document block, for example:
/*** @throws NoUserIdProvidedException*/
In the closure, the authentication provider or handling code does not make the warning go away, is there a way to comment or type hint the code to avoid false positives? I don't want to just turn off the inspection.
The way the guard works seemed a bit too complicated for static analysis, so I refactored to move the underlying custom code out of the guard and directly into the middleware, which worked and is now correctly detected abnormal.
class Authenticate { public function handle(Request $request, Closure $next, string|null $guard = null): mixed { try { $security = new Security(); $user = $security->middleware($request); $signedIn = !empty($user->id); // ... } catch (NoUserIdProvidedException) { // ... } // ... } }The security class is custom logic. The important thing is that the document block with @throws is close enough to be found by the IDE
class Security{ /** * @param Request $request * @return bool|object|null * @throws InvalidDomainUser * @throws NoDomainUserException * @throws NoTokenOnRecordException * @throws NoTokenProvidedException * @throws NoUserException * @throws NoUserIdProvidedException */ public function middleware(Request $request): object|bool|null { // .... } }