何がしたい?
LaravelにはFormRequestやGateといった「特定のユーザーに特定の操作を許可しない」という権限管理機能が備わっていますが、そこで弾かれたときのエラーメッセージが英語です。多言語対応のLaravelさんならそんなのサクッと変更できるでしょ!と思ったのですが、意外とさっくりできず、グーグル先生もなかなか教えてくれなかったので、僭越ながら穴埋め係させていただきます。
※この画面はAJAXでのHTTPエラーをswalで表示するという、参画しているアプリのフロント画面です。Laravel標準だと黒い画面か白い画面が出ると思います。
Laravel5.5で実装。ソース見る限りではLaravel5.3~Laravel6.0に対応。
結論
例外のハンドラに追加します。メソッドがすでにある場合は、parent::prepareException($e)
の前にコードを追加します。
/**
* 例外の型を変換する
*/
protected function prepareException(Exception $e)
{
// これを追加
if( $e instanceof \Illuminate\Auth\Access\AuthorizationException ) {
$e = new \Illuminate\Auth\Access\AuthorizationException(
'許可されていません',
$e->getCode(),
$e // $eがもともと持っていた情報を失わないように引き継ぐ
);
}
// ↑ あえてデフォルトの動作の前に実行する
$e = parent::prepareException($e);
return $e;
}
解説
AuthorizationException のデフォルトメッセージ
「This action is unauthorized」というのは AuthorizationException のデフォルトのメッセージなのですが、Laravel6.0でも、それはハードコーディングされています。
public function __construct($message = null, $code = null, Exception $previous = null)
{
parent::__construct($message ?? 'This action is unauthorized.', 0, $previous);
$this->code = $code ?: 0;
}
エラーや例外処理のメッセージ(例えば「Syntax Error」とか)が多言語対応していないのはふつうなことで、問題はそれをそのまま表示しようとすること。どこかで置き換えしてやるのが良さそうです。
どこで?
prepareException
例外処理ならHander。特定の例外の型変換をするprepareException が適任です。今回は型はそのまま、メッセージだけ載せ替えたい。
ただ、AuthorizationException はデフォルトの型変換として AccessDeniedHttpException に変換されています。
if ($e instanceof AuthorizationException) {
$e = new AccessDeniedHttpException($e->getMessage(), $e);
}
だったら、AccessDeniedHttpException のメッセージをカスタマイズすべき? うーむ悩ましいところですが。今回は 「AuthorizationExceptionのデフォルトメッセージを英語にしたい(その後 AccessDeniedHttpException に変換されてどう処理されるかは知らぬ)」という AuthorizationException に固有の問題なので AuthorizationException を変換対象としました。
なので、デフォルトの変換処理 parent::prepareException($e)
の前に型変換を行っています。
こんな記事も書いています
Laravelのちょっとマニアックな視点から、誰も書かない記事を書いています(笑
合わせてご覧いただけると幸いです(^^)