Symfony4のウェルカムページはどうやって表示されているのか

Symfony4プロジェクトを作成するときはSymfony Skeletonを使用することが推奨されている。

symfony.com

Symfony Skeletonは最小限、かつ空のSymfonyプロジェクトを生成するのだが、あまりに空っぽ過ぎてControllerすら1つも作成されない。
php bin/console debug:router とすると、1つもルーティングが定義されていないことがわかる。

 ------ -------- -------- ------ ------
  Name   Method   Scheme   Host   Path
 ------ -------- -------- ------ ------

しかし、この状態でもウェルカムページはちゃんと表示される。
一体どうやってウェルカムページを表示しているのか。

ウェルカムページを表示する処理はSymfony本体 vendor/symfony/http-kernel/EventListener/RouterListener.php に記述されている。

<?php
// vendor/symfony/http-kernel/EventListener/RouterListener.php
// ...
try {
    // ...
} catch (ResourceNotFoundException $e) {
    if ($this->debug && $e instanceof NoConfigurationException) {
        $event->setResponse($this->createWelcomeResponse());

        return;
    }
}
// ...
private function createWelcomeResponse()
{
    $version = Kernel::VERSION;
    $baseDir = realpath($this->projectDir).DIRECTORY_SEPARATOR;
    $docVersion = substr(Kernel::VERSION, 0, 3);

    ob_start();
    include __DIR__.'/../Resources/welcome.html.php';

    return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND);
}

ResourceNotFoundException が発生したときに、それがデバッグ環境で、かつ NoConfigurationException インスタンスだった場合に、ウェルカムページを作成して返していることがわかる。

NoConfigurationExceptionResourceNotFoundException を継承しており、 UrlMatcher#match のなかで、ルーティング定義がなく、かつトップページにアクセスしたときにthrowされる。

<?php
// vendor/symfony/routing/Matcher/UrlMatcher.php
// ...
public function match($pathinfo)
{
    // ...
    if (0 === count($this->routes) && '/' === $pathinfo) {
        throw new NoConfigurationException();
    }
    // ...
}

これがウェルカムページ表示の仕組み。

ちなみにこの実装から、"prod環境にするとウェルカムページは表示されずエラーが発生するのではないか"ということが推測できる。
実際にやってみる。

# .env
#...
# APP_ENV=devをprodにする
APP_ENV=prod
#...

トップページにアクセスしてみる。

Fatal error: Uncaught Symfony\Component\Routing\Exception\NoConfigurationException in ...

推測どおりエラーになった。