PHP之内置web服务器-php教程

资源魔 28 0

媒介

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/ServeCo妹妹and.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->serverCo妹妹and(), $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 serverCo妹妹and()
{
    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:

这里咱们能够看到一个区分就是以前我本人写的代码,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@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';

发现跟我以前写的路由文件相反。没错,我就是从这里抄过去的。

根本上 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) {
        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;
}

我正在下面的代码中进行了正文, 形容了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 php开发教程 php开发资料 php开发自学 web服务器

抱歉,评论功能暂时关闭!