前言
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/publicphp -S localhost:8000
然后这个时候就可以正常访问了。
那么现在有个问题,就是难道每次必须要进入public
文件夹才能启动web服务器吗,其实我们可以指定根目录的,那么可以使用如下命令:
cd /home/baoguoxiao/www/php/demophp -S localhost:8000 -t public/
那么现在有一个问题就是说,如果我们使用了单入口,而且还是用了PATHINFO模式。那么上面的可能就有问题了。
对此,我们可以使用如下方案:
cd /home/baoguoxiao/www/php/demophp -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://{$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(), // 对需要执行的<mark>6来源gaodaimacom搞#^代%!码网</mark><strong>搞gaodaima代码</strong>参数进行转义处理。这里的 server 就是我们之前说的路由文件,它在项目的根路径下 ProcessUtils::escapeArgument(base_path('server.php')) );}