なんでこんな設計になったの
TL;DR
launch.json で ignore キーを設定しましょう。
設定したらデバッガーの再起動を忘れずに。
"ignore": [ "**/vendor/laravel/framework/src/Illuminate/View/Compilers/BladeCompiler.php" ],
経緯
laravel 9.47.0 で発生した blade の字句解析処理の改修で、
例えば @if (Auth::user()?->isSystemAdmin()) のようにディレクティブ中に ) を用いる記述がある場合にエラーが発生するようになりました。
https://sibogli.hateblo.jp/entry/2023/01/20/204555
具体的には vendor/laravel/framework/src/Illuminate/View/Compilers/BladeCompiler.php
の hasEvenNumberOfParentheses() で、
以下の処理が Parse Error を投げます。
$tokens = token_get_all('<?php '.$expression); // ParseError: Unclosed '('
上記の $expression に当たる値は正規表現で抽出した blade ファイル上の文字列になりますが、
この正規表現のパターンが変更されたことにより当該エラーが発生するようになりました。
パターンマッチング処理している箇所は、同じく BladeComplier の compileStatements() になります。
9.47.0 から「正しい ) が見つかるまで再帰的にチェックしていく」というコメントと共に当該処理が追加されたので、
もはや token_get_all() がエラーを投げる場合もあるというのは想定通りのようにも思えます。
その上で対応を検討する必要があります。
改修自体の経緯
以下のあたりをきっかけとしています。
Escaping Blade directives with @@ is broken
https://github.com/laravel/framework/issues/45915
[9.x] Fixes blade escaped tags issue
https://github.com/laravel/framework/pull/45928
[9.x] Fixes blade tags issue #45424
https://github.com/laravel/framework/pull/45490
どう対処すればいいか
もうエラーが発生するのはどうしようもできないという状況を一度しっかりと受け止め、
xdebug の設定で当該ファイルのエラーをキャッチしないようにしました。
理想であれば関数単位で設定したいのですが、そのような設定項目はありませんでした。
(エラーを set_error_handler で扱う案はあったが、コードベースに変更は加えたくなかったのでここでは割愛)
vscode の launch.json に BladeCompiler を設定することで、このファイル上で発生したあらゆるエラーや例外がキャッチされなくなりました。
"ignore": [ "**/vendor/laravel/framework/src/Illuminate/View/Compilers/BladeCompiler.php" ],
また、https://github.com/xdebug/vscode-php-debug に記載されていた skipFiles, skipEntryPaths は機能しませんでした。