Laravelでログに出力されない500エラーが発生した時に疑う場所
先日、Laravel10で作ったとあるシステムを本番公開しようとしたら、500エラーが発生し解決に手間取りましたので共有させていただきたいと思います。
composer installやマイグレーションは事前に済ませており、時間になったらシンボリックリンクを公開領域に張るだけのはずでした。しかし、いざシンボリックリンクを張ってトップページにアクセスしてみると500エラーが発生しました。
APP_DEBUGをtrueにしてみてもレンタルサーバーのデフォルトの500エラーページが表示されるだけです。ログに何か出力されていないか確認するも何も書き込まれていませんでした。
この時点ですぐに解決の糸口がつかめず非常に焦りました。
1行ずつ処理を追う
試しに処理の起点となるpublic/index.phpの頭に
echo 'test';
を仕込んでみました。再び画面にアクセスすると「test」と表示されたのでシンボリックリンクは機能して画面アクセスはできている様子でした。
このままechoを1行ずつ進めていきどこでエラーが発生するか特定することにしました。
51行目の下記の処理の直前では「test1」が表示され、処理の直後にechoを置くとエラーが発生しました。
echo 'test1';
$response = $kernel->handle(
$request = Request::capture()
)->send();
echo 'test2';
引数の$requestに問題ないか調べるために52行目の処理だけ取り出してdd ()を仕掛けてみます。
dd($request = Request::capture());
$response = $kernel->handle(
$request = Request::capture()
)->send();
$requestの中身はセットされているので「Request::capture()」は動いている様子です。ちなみにLaravelのヘルパーは34行目の
require __DIR__.'/../vendor/autoload.php';
を読み込んだ後なら使用可能です。
続いて、Karnelクラスの処理を追っていきます。Karnelクラスは「vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php」にあります。まずはhandleメソッドにdump()を仕掛けていきます。
public function handle($request)
{
$this->requestStartedAt = Carbon::now();
try {
dump('test1');
$request->enableHttpMethodParameterOverride();
dump('test2');
$response = $this->sendRequestThroughRouter($request);
dump('test3');
} catch (Throwable $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
}
$this->app['events']->dispatch(
new RequestHandled($request, $response)
);
return $response;
}
「test3」が表示されないので「$this->sendRequestThroughRouter($request)」の処理を追います。下記のようにdump()を仕掛けました。
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
dump('test1');
Facade::clearResolvedInstance('request');
dump('test2');
$this->bootstrap();
dump('test3');
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
ここも「test3」が表示されないので「$this->bootstrap();」の処理を追います。下記のようにdump()を仕掛けました。
public function bootstrap()
{
if (! $this->app->hasBeenBootstrapped()) {
dump('test1');
$this->app->bootstrapWith($this->bootstrappers());
dump('test2');
}
}
「test2」が表示されないので「$this->bootstrappers()」の処理を追います。このメソッドは下記のプロパティを返すだけのゲッターです。
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
鋭い人はここでピンとくるかもしれません。
続いて「$this->app->bootstrapWith()」を追います。Applicationクラスは「vendor/laravel/framework/src/Illuminate/Foundation/Application.php」にあります。下記のbootstrapWithメソッド中のforeachにdumpを仕掛けてみます。
public function bootstrapWith(array $bootstrappers)
{
$this->hasBeenBootstrapped = true;
foreach ($bootstrappers as $bootstrapper) {
dump($bootstrapper);
$this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);
$this->make($bootstrapper)->bootstrap($this);
$this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
}
}
$bootstrappersは上記のKarnelクラスの$bootstrappersです。配列の中身が全て出力されず、1つ目の「 "Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables"」を出力して止まってしまいました。
エラー箇所を突き止める
ここで「LoadEnvironmentVariables」という名前から、ようやく環境変数の読み込みでエラーが起きていることに気づきました。
環境変数を見直して記法に誤りがあったことを発見し、無事解決に至りました。
まとめ
Laravelの起動処理でエラーが起こるとログに出力されない場合がある
その場合は環境変数の記述を見直すこと