PHP は 5.4 以降、組み込み Web サーバーを提供しています。
これは主にローカル開発に使用されます。オンライン環境ではご利用いただけません。今回はこのツールの使い方を紹介します。
最初に、プロジェクト ディレクトリが /home/baoguoxiao/www/php/demo
であり、外部からアクセスできるディレクトリが ## であると仮定します。 #/home/baoguoxiao /www/php/demo/public。この場合、アクセス ポートは
8000、エントリ ファイルは
index.php および
index.html です。次に、次のコマンドを実行します。
cd /home/baoguoxiao/www/php/demo/public php -S localhost:8000
public フォルダーに入る必要がありますか? 実際、ルート ディレクトリを指定でき、その後、次のコマンド:
cd /home/baoguoxiao/www/php/demo php -S localhost:8000 -t public/
cd /home/baoguoxiao/www/php/demo php -S localhost:8000 router.php
/** * 对URL进行解析,并获取请求的文件名 */$uri = urldecode(parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH));/** * 判断是否存在该文件,如果不存在,则直接继续加载入口文件 */if ($uri !== "/" && file_exists(__DIR__ . "$uri")) { return false; }/** * 加载入口文件 */require_once "./index.php";
インストール セクションでは、PHP 組み込み Web サーバーを使用して外部アクセスを実現できるコマンドが紹介されています。実装されたコマンドは次のとおりです:
php artisan serve
/** * 执行命令. * * @return int * * @throws \Exception */ public function handle() { // 切换路径到 public 目录 chdir(public_path()); // 在命令台进行输出相关内容 $this->line("<info>Laravel development server started:</info> <http://{$this->host()}:{$this->port()}>"); // 执行外部程序,并且 $status 为系统的返回状态 passthru($this->serverCommand(), $status); // $status 为0 表示执行正常, 为其他大于0的数字表示出现了错误,有可能是端口被抢占了,这个时候就会接着判断是否进行再次尝试 if ($status && $this->canTryAnotherPort()) { // 对绑定的端口号加1 默认是8000, 如果失败则重试端口号为8001,再次失败重试端口号为8002,以此类推。 $this->portOffset += 1; // 再次调用此程序 return $this->handle(); } // 返回状态值 return $status; } /** * 获取完整的 server 命令. * * @return string */ protected function serverCommand() { return sprintf('%s -S %s:%s %s', // 获取PHP可执行命令的路径 ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false)), // 获取需要绑定的host $this->host(), // 获取需要绑定的端口 $this->port(), // 对需要执行的参数进行转义处理。这里的 server 就是我们之前说的路由文件,它在项目的根路径下 ProcessUtils::escapeArgument(base_path('server.php')) ); }
cd ./public php -S 0.0.0.0:8000 ../server.php
note:ここで違いがわかります。これは、以前に書いたコードです。 , hostsは全てlocalhostですが、ここに書かれているのは0.0.0.0です。これら 2 つの違いは何ですか? 実際、違いは非常に単純です。たとえば、前に書いたローカルホストにバインドされている IP は 127.0.0.1 です。これはループバック アドレスに相当するため、ローカル IP のみにアクセスを許可します。 0.0.0.0 は、IP に制限がなく、すべての IP にアクセスできることを意味します。次に、プロジェクトのルート ディレクトリにある
server.php:
/** * Laravel - A PHP Framework For Web Artisans * * @package Laravel * @author Taylor Otwell <taylor@laravel.com> */ $uri = urldecode( parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ); // 这个文件允许我们从内置 PHP web 服务器中模拟 Apache 的 "mod_rewrite" 功能. // 这提供了一种测试 Laravel 应用程序的便捷方法, // 而无需在此安装"真正的" web 服务器软件。 if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { return false; } require_once __DIR__.'/public/index.php';
web-server-bundle というコンポーネントがあり、このコンポーネントは Laravel と同じ機能を持っています。 Web サーバーを使用すると、ブラウザーを介してアプリケーションにアクセスできます。
基本的な操作については、ここでは主に Symfony の実装方法について説明します。コードがあります。 Symfony では次のようになります:public function start(WebServerConfig $config, $pidFile = null) { // 获取默认的PID文件位置 $pidFile = $pidFile ?: $this->getDefaultPidFile(); // 判断是否在运行,如果运行则提示已经在监听了 if ($this->isRunning($pidFile)) { throw new \RuntimeException(sprintf('A process is already listening on http://%s.', $config->getAddress())); } // fork了一个子进程,如果成功,会有两个进程进行同时执行下面的文件,父进程,也就是当前执行的进程会返回子进程的PID,而子进程则返回的PID为0, // 如果失败,则子进程不会创建,并且父进程会返回的pid为-1。更多内容可查看 https://www.php.net/manual/zh/function.pcntl-fork.php $pid = pcntl_fork(); // 表示fork进程失败 if ($pid < 0) { throw new \RuntimeException('Unable to start the server process.'); } // 进入这个判断,表示执行的是父进程,表示不用继续向下执行 if ($pid > 0) { return self::STARTED; } // 从此往后是子进程运行,首先通过 posix_setsid 变为守护进程,意思是使其脱离终端的管理,自立门户,谁也没办法管理这个进程,除了PID。 if (posix_setsid() < 0) { throw new \RuntimeException('Unable to set the child process as session leader.'); } // 创建命令,命令类似Laravel,不过这里的路由文件跟Laravel类似。也是处理加载规则,并加载入口文件。具体的router.php 路径为: // vendor\symfony\web-server-bundle/Resources/router.php // 下面是禁用输出并且开始运行 $process = $this->createServerProcess($config); $process->disableOutput(); $process->start(); // 判断是否运行成功 if (!$process->isRunning()) { throw new \RuntimeException('Unable to start the server process.'); } // 写入PID文件 file_put_contents($pidFile, $config->getAddress()); // 检测PID文件,如果PID文件删除了,那么进程就立即退出。 while ($process->isRunning()) { if (!file_exists($pidFile)) { $process->stop(); } sleep(1); } // 返回停止的状态 return self::STOPPED; } /** * 启动PHP内置web服务器 * @return Process The process */ private function createServerProcess(WebServerConfig $config) { // 查找PHP的可执行程序 $finder = new PhpExecutableFinder(); if (false === $binary = $finder->find(false)) { throw new \RuntimeException('Unable to find the PHP binary.'); } $xdebugArgs = ini_get('xdebug.profiler_enable_trigger') ? ['-dxdebug.profiler_enable_trigger=1'] : []; // 实例化PHP要执行的命令 php_path -dvariables_order=EGPCS -S 127.0.0.1:8000 vendor\symfony\web-server-bundle/Resources/router.php $process = new Process(array_merge([$binary], $finder->findArguments(), $xdebugArgs, ['-dvariables_order=EGPCS', '-S', $config->getAddress(), $config->getRouter()])); // 设置工作目录 $process->setWorkingDirectory($config->getDocumentRoot()); // 设置超时时间 $process->setTimeout(null); // 设置环境变量 if (\in_array('APP_ENV', explode(',', getenv('SYMFONY_DOTENV_VARS')))) { $process->setEnv(['APP_ENV' => false]); $process->inheritEnvironmentVariables(); } // 返回相关变量 return $process; }
pcntl_fork
、この拡張機能は Windows ではサポートされていません。そのため、Symfony フレームワークは、プログラムを実行するために php bin/console server:run コマンドを使用するように求めるメッセージを表示します。
php -S コマンドに依存しません。私はコードのこの部分を完全には理解していませんが、これについてはいくつかの別の章で説明できると思います。将来的にはこのような機会があれば幸いです。
PHP チュートリアル # 列にアクセスして学習してください。
以上がPHP組み込みWebサーバーの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。