使用PHP内置Web服务器进行Fatfree路由

问题描述 投票:2回答:2

我正在学习无脂肪的路线,发现它表现得出乎意料。

这是我在index.php中的代码:

$f3 = require_once(dirname(dirname(__FILE__)). '/lib/base.php');
$f3 = \Base::instance();

echo 'received uri: '.$_SERVER['REQUEST_URI'].'<br>';

$f3->route('GET /brew/@count',
    function($f3,$params) {
        echo $params['count'].' bottles of beer on the wall.';
    }
);

$f3->run();

这是我访问的URL:http://xx.xx.xx.xx:8090/brew/12

我收到404错误:

received uri: /brew/12
Not Found

HTTP 404 (GET /12)

奇怪的是,F3中的URI现在是“/ 12”而不是“/ brew / 12”,我想这就是问题所在。

当我检查base.php(3.6.5),$ this-> hive ['BASE'] =“/ brew”和$ this-> hive ['PATH'] =“/ 12”时。但是如果F3只使用$ this-> hive ['PATH']来匹配预定义的路由,它将无法匹配它们。

如果我将路线更改为:

$f3->route('GET /brew',

并使用URL:http://xx.xx.xx.xx:8090/brew,然后路由匹配没有问题。在这种情况下,$ this-> hive ['BASE'] =“”和$ this-> hive ['PATH'] =“/ brew”。如果F3将$ this-> hive ['PATH']与预定义路由进行比较,则它们相互匹配。

顺便说一句,我正在使用PHP的内置Web服务器,因为$ _SERVER ['REQUEST_URI'](由base.php使用)返回正确的URI,我认为我的URL重写没有任何问题。 .htrouter.php。

任何的想法?我在这里想念的是什么?

在这里添加.htrouter.php的内容

<?php

#get the relative URL
$uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));

#if request to a real file (such as a html, image, js, css) then leave it as it is
if ($uri !== '/' && file_exists(__DIR__  . $uri)) {
    return false;
}

#if request virtual URL then pass it to the bootstrap file - index.php
$_GET['_url'] = $_SERVER['REQUEST_URI'];
require_once __DIR__ . './public/index.php';
fat-free-framework php-builtin-server
2个回答
2
投票

您的问题与您使用PHP内置Web服务器的方式直接相关。

正如PHP docs中所述,这是服务器处理请求的方式:

URI请求从启动PHP的当前工作目录提供,除非使用-t选项指定显式文档根目录。如果URI请求未指定文件,则返回给定目录中的index.php或index.html。如果两个文件都不存在,则index.php和index.html的查找将在父目录中继续,依此类推,直到找到一个或者已到达文档根目录。如果找到index.php或index.html,则返回它,并将$ _SERVER ['PATH_INFO']设置为URI的尾部。否则返回404响应代码。

如果在启动Web服务器时在命令行上给出了PHP文件,则将其视为“路由器”脚本。该脚本在每个HTTP请求的开头运行。如果此脚本返回FALSE,则按原样返回请求的资源。否则,脚本的输出将返回给浏览器。

这意味着,默认情况下(没有路由器脚本),Web服务器在将不存在的URI路由到文档根index.php文件方面做得非常好。

换句话说,假设您的文件结构如下:

lib/
    base.php
    template.php
    etc.
public/
    index.php

以下命令足以启动服务器并将请求正确分派给框架:

php -S 0.0.0.0:8090 -t public/

或者,如果您直接从公共/文件夹运行命令:

cd public
php -S 0.0.0.0:8090

请注意,应用程序的工作目录取决于您调用该命令的文件夹。为了利用这个值,我强烈建议你在chdir(__DIR__);文件的顶部添加public/index.php。这样,所有后续的require调用都将相对于你的public/文件夹。例如:$f3 = require('../lib/base.php');

Routing file-style URIs

默认情况下,内置服务器不会将未使用的文件URI传递给index.php,如下所述:

如果URI请求未指定文件,则返回给定目录中的index.php或index.html

因此,如果您计划定义一些带点的路线,例如:

$f3->route('GET /brew.json','Brew->json');
$f3->route('GET /brew.html','Brew->html');

然后它将无法工作,因为PHP不会将请求传递给index.php

在这种情况下,您需要调用自定义路由器,例如您尝试使用的.htrouter.php。唯一的事情是你的.htrouter.php显然是为不同的框架设计的(F3不关心$_GET['url']但关心$_SERVER['SCRIPT_NAME']

以下是适用于F3的.htrouter.php示例:

// public directory definition
$public_dir=__DIR__.'/public';

// serve existing files as-is
if (file_exists($public_dir.$_SERVER['REQUEST_URI']))
    return FALSE;

// patch SCRIPT_NAME and pass the request to index.php
$_SERVER['SCRIPT_NAME']='index.php';
require($public_dir.'/index.php');

注意:$public_dir变量应根据.htrouter.php文件的位置进行设置。

例如,如果你打电话:

php -S 0.0.0.0:8090 -t public/ .htrouter.php

它应该是$public_dir=__DIR__.'/public'

但如果你打电话:

cd public
php -S 0.0.0.0:8090 .htrouter.php

它应该是$public_dir=__DIR__


0
投票

好的,我检查了base.php并发现当f3计算基URI时,它使用$ _SERVER ['SCRIPT_NAME']。

$base='';
if (!$cli)
    $base=rtrim($this->fixslashes(
        dirname($_SERVER['SCRIPT_NAME'])),'/');

如果我们让web服务器直接将所有请求转发到index.php,那么_SERVER ['SCRIPT_NAME'] = /index.php,在这种情况下,base是''。

如果我们通过.htrouter.php使用URL重写到index.php,那么_SERVER ['SCRIPT_NAME'] = / brew / 12,在这种情况下,base是'/ brew'导致问题。

由于我将使用URL重写,我必须注释掉if语句并确保base =''。

感谢xfra35提供线索。

© www.soinside.com 2019 - 2024. All rights reserved.