1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHPフレームワークFLow】Flowのserver:runコマンド実行時の動きについて

Last updated at Posted at 2024-02-21

初めに

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);
    }
  1. Scripts::buildPhpCommandでPHPコマンドを作成
  2. PHPコマンドにオプションを付与
  3. 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"
  1. プロジェクトパスやコンテキストなどの環境変数を設定
  2. 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へと処理がたどり着く仕組みです。

PhpDevelopmentServerRouter.php
<?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内部の処理を知るのは面白いですね。
また何か分かったことがあれば記事にする予定です。

ここまで読んでいただきありがとうございました!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?