先週SymfonyWorld 2021 Summer Editionのトークで @TobiasNyholm さんが紹介していたRuntimeコンポーネントを早速使ってみたのでご紹介します!

Runtimeコンポーネントとは

Symfony5.3から導入された新しいコンポーネントです。
実行環境(php-fpm, AWS Lambda, PaaS, swoole, …)ごとのフロントコントローラの違いをクラスとして提供してくれます。
https://symfony.com/doc/current/components/runtime.html

Runtimeコンポーネントで何が嬉しいか?

Runtimeコンポーネント導入前まで、 symfony new して作ったSymfonyプロジェクトは、スタンダードなApache・nginxで動かすことを前提にした public/index.php だけが配布されていました。 それ以外の特殊な実行環境(たとえば「SymfonyをAWS Lambdaで」とか)でSymfonyを動かそうと思ったら、 $_SERVER を自前でセットする等のやり方をググって、自力で public/index.phpbin/console をカスタマイズする必要がありました。

Runtimeコンポーネントは各実行環境ごとのカスタマイズ内容を、再利用可能な形でSymfonyコンポーネントとして提供してくれるため、自力でカスタマイズを適用する必要はなくなりました :relaxed:

既存のSymfonyプロジェクトにRuntimeコンポーネントを導入する方法

前提として、Symfony5.3まで更新してあるプロジェクトが対象です。

symfony/runtime導入

composer require symfony/runtime

vendor/autoload_runtime.php作成, public/index.phpの更新

composer recipes:install symfony/framework-bundle -v --force

config/framework.yamlに自分の設定を書き込んでいる場合は、設定が初期状態まで巻き戻ってしまうため、git diffを見て自分の設定した部分は復元しましょう。

bin/consoleの更新

composer recipes:install symfony/console -v --force



必要な変更をコミット後、 symfony server:start してみると、今まで通りにアプリケーションが動くことを確認できると思います(私はできました)。
vendor/autoload_runtime.php を見てみると、デフォルトのRuntimeとして Symfony\Component\Runtime\SymfonyRuntime が指定されていること、Runtimeを変更したい場合は $_SERVER['APP_RUNTIME'] を変更すれば良いことがわかります。

<?php

// autoload_runtime.php @generated by Symfony Runtime

if (true === (require_once __DIR__.'/autoload.php') || empty($_SERVER['SCRIPT_FILENAME'])) {
    return;
}

if (PHP_VERSION_ID < 80000 && in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
    ob_start();
    $app = require $_SERVER['SCRIPT_FILENAME'];
    ob_end_clean();
} else {
    $app = require $_SERVER['SCRIPT_FILENAME'];
}

if (!is_object($app)) {
    throw new TypeError(sprintf('Invalid return value: callable object expected, "%s" returned from "%s".', get_debug_type($app), $_SERVER['SCRIPT_FILENAME']));
}

$runtime = $_SERVER['APP_RUNTIME'] ?? 'Symfony\\Component\\Runtime\\SymfonyRuntime';
$runtime = new $runtime(($_SERVER['APP_RUNTIME_OPTIONS'] ?? []) + [
  'project_dir' => dirname(__DIR__, 1),
]);

[$app, $args] = $runtime
    ->getResolver($app)
    ->resolve();

$app = $app(...$args);

exit(
    $runtime
        ->getRunner($app)
        ->run()
);

感想

ますますコアなアプリケーション部分の開発に集中できる方向に進化してくれるSymfonyがやっぱり大好きだな〜と思いました。