前言
#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
資料夾才能啟動web伺服器嗎,其實我們可以指定根目錄的,那麼可以使用如下指令:
cd /home/baoguoxiao/www/php/demo php -S localhost:8000 -t public/
那麼現在有一個問題是說,如果我們使用了單入口,而且還是用了PATHINFO模式。那麼上面的可能就有問題了。
對此,我們可以使用以下方案:
cd /home/baoguoxiao/www/php/demo php -S localhost:8000 router.php
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";
透過這個路由文件,我們就可以支援目前常用的開發情況了。
框架參考
上面的方式是我們自己的實現,那麼我們也可以看看相關知名框架的實作方法。
例如 Laravel 和 Symfony。
Laravel
在Laravel中的安裝一節中介紹了一個命令可以使用PHP內建web伺服器實現外部存取的命令。實作的指令是:
php artisan serve
我們可以看相關程式碼:
具體的檔案路徑為:vendor/laravel/framework/src/Illuminate/Foundation/Console/ServeCommand.php
/** * 执行命令. * * @return int * * @throws \Exception */ public function handle() { // 切换路径到 public 目录 chdir(public_path()); // 在命令台进行输出相关内容 $this->line("<info>Laravel development server started:</info> <http:>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')) ); }</http:>
對上面的命令進行翻譯一下,實際上就是執行的
cd ./public php -S 0.0.0.0:8000 ../server.php
#note:
這裡我們可以看到一個差異就是之前我自己寫的程式碼,host 都是localhost, 但這裡寫的是0.0.0.0。這兩個有什麼差別呢?
其實差別很簡單,像是我之前寫的 localhost 綁定的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> */ $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';</taylor>
發現跟我之前寫的路由檔案相同。沒錯,我就是從這裡抄來的。
基本上 Larvel 的實作方法就是這樣了。
Symfony
如果你在使用Symfony 框架話,發現Symfony有一個元件叫做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) { return self::STARTED; } // 从此往后是子进程运行,首先通过 posix_setsid 变为守护进程,意思是使其脱离终端的管理,自立门户,谁也没办法管理这个进程,除了PID。 if (posix_setsid() 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; }
我在上面的程式碼中進行了註解, 描述了Symfony是如何啟動的.
裡面有一個問題就是使用pcntl_fork
, 該擴充功能在Windows中是不受支援的. 所以Symfony框架會提示使用php bin/console server:run
指令執行程式.
未來展望
#其實還有一個方式, 就是Workman 是透過自身的實現的web伺服器,它並沒有借助php -S
指令。這一塊的代碼我還沒吃透,我覺得這個也可以單獨拎幾章出來講。希望以後有這個機會。
總結
透過我們學習PHP 指令實現web伺服器存取以及對Laravel 和Symfony 框架的分析, 讓我了解到在Windows的開發過程中,我們完全可以藉助該方式來擺脫對web伺服器的依賴.既能方便我們在Windows環境進行開發並且學習了PHP一個技巧.感覺挺好的.
大家如果對此有什麼疑問可以評論進行交流.
#更多PHP相關技術文章,請造訪PHP教學欄位進行學習!
以上是PHP之內建web伺服器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

PHPSession失效的原因包括配置錯誤、Cookie問題和Session過期。 1.配置錯誤:檢查並設置正確的session.save_path。 2.Cookie問題:確保Cookie設置正確。 3.Session過期:調整session.gc_maxlifetime值以延長會話時間。

在PHP中調試會話問題的方法包括:1.檢查會話是否正確啟動;2.驗證會話ID的傳遞;3.檢查會話數據的存儲和讀取;4.查看服務器配置。通過輸出會話ID和數據、查看會話文件內容等方法,可以有效診斷和解決會話相關的問題。

多次調用session_start()會導致警告信息和可能的數據覆蓋。 1)PHP會發出警告,提示session已啟動。 2)可能導致session數據意外覆蓋。 3)使用session_status()檢查session狀態,避免重複調用。

在PHP中配置會話生命週期可以通過設置session.gc_maxlifetime和session.cookie_lifetime來實現。 1)session.gc_maxlifetime控制服務器端會話數據的存活時間,2)session.cookie_lifetime控制客戶端cookie的生命週期,設置為0時cookie在瀏覽器關閉時過期。

使用數據庫存儲會話的主要優勢包括持久性、可擴展性和安全性。 1.持久性:即使服務器重啟,會話數據也能保持不變。 2.可擴展性:適用於分佈式系統,確保會話數據在多服務器間同步。 3.安全性:數據庫提供加密存儲,保護敏感信息。

在PHP中實現自定義會話處理可以通過實現SessionHandlerInterface接口來完成。具體步驟包括:1)創建實現SessionHandlerInterface的類,如CustomSessionHandler;2)重寫接口中的方法(如open,close,read,write,destroy,gc)來定義會話數據的生命週期和存儲方式;3)在PHP腳本中註冊自定義會話處理器並啟動會話。這樣可以將數據存儲在MySQL、Redis等介質中,提升性能、安全性和可擴展性。

SessionID是網絡應用程序中用來跟踪用戶會話狀態的機制。 1.它是一個隨機生成的字符串,用於在用戶與服務器之間的多次交互中保持用戶的身份信息。 2.服務器生成並通過cookie或URL參數發送給客戶端,幫助在用戶的多次請求中識別和關聯這些請求。 3.生成通常使用隨機算法保證唯一性和不可預測性。 4.在實際開發中,可以使用內存數據庫如Redis來存儲session數據,提升性能和安全性。

在無狀態環境如API中管理會話可以通過使用JWT或cookies來實現。 1.JWT適合無狀態和可擴展性,但大數據時體積大。 2.Cookies更傳統且易實現,但需謹慎配置以確保安全性。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器