В Laravel 11 обработка исключений перенесена в файл bootstrap/app.php
. Я пытаюсь поймать AuthorizationException
и вернуть пользователя на панель управления с сообщением 403:
// bootstrap/app.php
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Request;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
return Application::configure(basePath: dirname(__DIR__))
...
->withExceptions(function (Exceptions $exceptions) {
$exceptions->render(function (AuthorizationException $e, Request $request) {
return redirect()
->route('dashboard')
->withErrors($e->getMessage());
});
...
})
...
->create();
Но это не работает. Этот вошедший в систему пользователь не может видеть конечную точку /users
, но мой обработчик исключений не обрабатывает ее. Они должны видеть свою панель управления. (Мой .env
показывает APP_DEBUG=true
.)
(Используйте barryvdh/laravel-debugbar
на этом скриншоте)
Форум Laracasts на это чудесно ответил: https://laracasts.com/discuss/channels/laravel/how-to-catch-a-policy-response-Exception
Изменена подсказка типа исключения, чтобы просто Throwable
проверить все, что было обнаружено:
$exceptions->render(function (Throwable $e, Request $request) {
dd($e);
...
});
... и похоже, что он пропустил исключение AuthorizationException и передал Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
Теперь вопрос: «Почему?» Почему в документации Laravel не содержится более подробной информации о том, как обрабатывать распространенные исключения? В любом случае, это решено, но у других может возникнуть такая же проблема, поэтому вот мое решение:
<?php
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
return Application
::configure(basePath: dirname(__DIR__))
...
->withExceptions(function (Exceptions $exceptions) {
$exceptions->render(function (Throwable $e) {
if ( $e instanceof AccessDeniedHttpException ) {
/* This may be overly specific, but I want to handle other
potential AccessDeniedHttpExceptions when I come
across them */
if ( $e->getPrevious() instanceof AuthorizationException ) {
return redirect()
->route('dashboard')
->withErrors($e->getMessage());
}
}
});
})
->create();
Исключение не пропускается, оно оборачивается. Подробности смотрите здесь.
вместо того, чтобы придумывать хакерские решения, было бы лучше спросить об этом сопровождающих, поскольку это, скорее всего, связано с Laravel 11.