初めに
Flowでは./flow server:run
というコマンドを叩くことで、開発用の簡易的なサーバを立てることができます。
今回は、このコマンドでは実際にどんなことが行われているのかを見ていきます。
server:runコマンド
server:run
コマンドはシンプルです。
以下のコマンドを実行するだけで、簡単にWebサーバを立てることができます。
$ ./flow server:run
Server running. Please go to http://127.0.0.1:8081 to browse the application.
[Wed Feb 21 20:49:17 2024] PHP 8.1.25 Development Server (http://127.0.0.1:8081) started
ホストとポートはオプションで設定可能です。
$ ./flow server:run --host 127.0.0.2 --port 9999
Server running. Please go to http://127.0.0.2:9999 to browse the application.
[Wed Feb 21 21:09:52 2024] PHP 8.1.25 Development Server (http://127.0.0.2:9999) started
実際に何が起きてるのか
このコマンドが実行されるとき、Flowはどのような動きをしているのでしょうか。
たどってみましょう。
コマンド実行時
./flow server:run
のコマンド実行時、ServerCommandControllerのrunCommand()の処理が走ります。
public function runCommand(string $host = '127.0.0.1', int $port = 8081)
{
$command = Scripts::buildPhpCommand($this->settings);
$address = sprintf('%s:%s', $host, $port);
$command .= ' -S ' . escapeshellarg($address) . ' -t ' . escapeshellarg(FLOW_PATH_WEB) . ' ' . escapeshellarg(FLOW_PATH_FLOW . '/Scripts/PhpDevelopmentServerRouter.php');
$this->outputLine('Server running. Please go to <b>http://' . $address . '</b> to browse the application.');
exec($command);
}
-
Scripts::buildPhpCommand
でPHPコマンドを作成 - PHPコマンドにオプションを付与
-
exec()
でコマンドを実行
という流れです。
exec()
の引数が実行されるphpコマンドです。このコマンドで何が起きているのでしょうか。
実際に渡されるコマンドを確認してみる
exec()
コマンドで実行されるコマンドを実際に出力してみました。
SET FLOW_ROOTPATH=C:/Path/to/Project/&
SET FLOW_PATH_TEMPORARY_BASE=C:/Path/to/Project/Data//Temporary&
SET FLOW_CONTEXT=Development&
SET XDEBUG_CONFIG=idekey=FLOW_SUBREQUEST remote_port=9001&
"C:/php-8.1.25/php.exe" -c "C:\php-8.1.25\php.ini" -S "127.0.0.1:8081" -t "C:/Path/to/Project/Web/" "C:/Path/to/Project/Packages/Framework/Neos.Flow/Classes/Core/../..//Scripts/PhpDevelopmentServerRouter.php"
- プロジェクトパスやコンテキストなどの環境変数を設定
- phpコマンドを実行
という流れでした。
ここで実行してるphp
コマンドの詳細を調べてみました。
php -S
はビルドインウェブサーバを立てるコマンド
このコマンドはPHPのビルドインウェブサーバを立てるコマンドのようです。
ビルドインウェブサーバとはPHPが提供する組み込みの開発サーバのことで、ApacheなどのWebサーバを立てることなくWebアプリケーションの動作確認をおこなうことができる機能になります。
以下のように、PHPコマンドに-S
オプションをつけて実行することで簡単にWebサーバを立てることができます。
php -S localhost:8000 /Path/to/Router.php
-S
オプションの後にサーバのホストとポート番号を指定できます。
最後の引数にはルーター(リクエストが来たときに実行するPHPファイル)のパスを指定しています。
その他主要な引数は以下です。
オプション | 説明 |
---|---|
-c | php.iniファイルを指定することができる |
-t | ドキュメントルートを指定することができる |
ビルドインウェブサーバは開発用に提供されている機能です。本番用のサーバには使用できませんのでご注意ください。(公式ドキュメントにもその旨が記載されておりますので、気になる方はご参照ください)
改めて実行されたコマンドを見てみる
改めてコマンドを見てみましょう。
SET FLOW_ROOTPATH=C:/Path/to/Project/&
SET FLOW_PATH_TEMPORARY_BASE=C:/Path/to/Project/Data//Temporary&
SET FLOW_CONTEXT=Development&
SET XDEBUG_CONFIG=idekey=FLOW_SUBREQUEST remote_port=9001&
"C:/php-8.1.25/php.exe" -c "C:\php-8.1.25\php.ini" -S "127.0.0.1:8081" -t "C:/Path/to/Project/Web/" "C:/Path/to/Project/Packages/Framework/Neos.Flow/Classes/Core/../..//Scripts/PhpDevelopmentServerRouter.php"
ルーターファイルで指定されているPhpDevelopmentServerRouter.phpはFlowにおける開発用のルーターファイルになります。
リクエストが来るとまずこのファイルが実行されます。その後、最後にある$bootstrap->run();
が実行され、最終的にControllerへと処理がたどり着く仕組みです。
<?php
/**
* Entry Point (Router) for PHP's embedded HTTP server. Use ./flow server:run to execute.
*/
if (strpos($_SERVER['REQUEST_URI'], '_Resources/') !== false) {
// published resources shall be served directly
return false;
}
require(__DIR__. '/../Classes/Core/Bootstrap.php');
if (DIRECTORY_SEPARATOR !== '/' && trim(getenv('FLOW_ROOTPATH'), '"\' ') === '') {
$absoluteRootpath = dirname(realpath(__DIR__ . '/../../../'));
if (realpath(getcwd()) === $absoluteRootpath) {
$_SERVER['FLOW_ROOTPATH'] = '.';
} elseif (strlen(getcwd()) > strlen($absoluteRootpath)) {
$amountOfPathsToSkipBack = substr_count(getcwd(), DIRECTORY_SEPARATOR) - substr_count($absoluteRootpath, DIRECTORY_SEPARATOR);
$_SERVER['FLOW_ROOTPATH'] = implode('/', array_fill(0, $amountOfPathsToSkipBack, '..'));
} else {
$_SERVER['FLOW_ROOTPATH'] = substr($absoluteRootpath, strlen(getcwd()) + 1);
}
} else {
$_SERVER['FLOW_ROOTPATH'] = trim(getenv('FLOW_ROOTPATH'), '"\' ') ?: dirname($_SERVER['PHP_SELF']);
}
// Script filename and script name must "emulate" index.php, to not break routing
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['FLOW_ROOTPATH'] . 'Web/index.php';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$context = \Neos\Flow\Core\Bootstrap::getEnvironmentConfigurationSetting('FLOW_CONTEXT') ?: 'Development';
$bootstrap = new \Neos\Flow\Core\Bootstrap($context);
$bootstrap->run();
終わりに
今回はFlowのserver:run
コマンドが実行されたときの処理についてまとめました。
FW内部の処理を知るのは面白いですね。
また何か分かったことがあれば記事にする予定です。
ここまで読んでいただきありがとうございました!