【问题标题】:Routing PHP 5.4+ Built-in Web Server like .htaccess路由 PHP 5.4+ 内置 Web 服务器,如 .htaccess
【发布时间】:2015-01-04 12:58:20
【问题描述】:

我已经开始使用 PHP 5.6 的内置网络服务器,使用以下命令:

php -S localhost:80

我以前使用过 WAMP 服务器。并且手册还说,如果您为上述命令提供路由器脚本,请说:

php -S localhost:80 router.php

我们可以实现类似.htaccess。但是我找不到关于如何进行重定向或包含的可靠教程。现在,我的.htaccess 文件有以下内容:

RewriteEngine On
RewriteRule (.*)-(.*)\.htm$ ./?page=$1&sub=$2&%{QUERY_STRING} 
RewriteRule ^([^/]*)\.htm$ ./?page=$1&%{QUERY_STRING} [L]

我应该在router.php 中添加什么以实现与 Apache Web 服务器中相同的输出?提前致谢。

【问题讨论】:

  • mod_rewrite.php。尽管在路由器脚本中重新实现两行正则表达式以适应 REQUEST_URI+QUERY_STRING 肯定会更简单。

标签: php apache .htaccess php-builtin-server


【解决方案1】:

老问题,但这是一个简单的版本:

<?php
    /*  Friendly Urls
        ================================================
        RewriteEngine On
        RewriteCond %{SCRIPT_FILENAME} !-f [NC]
        RewriteCond %{SCRIPT_FILENAME} !-d [NC]
        RewriteRule ^(.+)$ /index.php?page=$1 [QSA,L]
        ================================================ */

    $root=__dir__;

    $uri=parse_url($_SERVER['REQUEST_URI'])['path'];
    $page=trim($uri,'/');   

    if (file_exists("$root/$page") && is_file("$root/$page")) {
        return false; // serve the requested resource as-is.
        exit;
    }

    $_GET['page']=$page;
    require_once 'index.php';
?>

通过这种方式,您可以使用普通的index.php,您可能已经使用过,例如 Apache 服务器。

【讨论】:

  • 最简单的答案。谢谢!
  • 这是针对GET 请求的吗?
  • @AbhilashKishore 在.htaccess 版本中,是的,这将转换为GET 请求。在router.php 版本中,没有技术原因不能将其设为POST 请求。但是,请记住,重点是将路径转换为请求,所以我看不到任何意义。
【解决方案2】:
<?php
    $_matches = array();

    /**
     * Initialize the rewrite environment.
     */
    function initialize() {
        set_environment($_SERVER['REQUEST_URI']);
    }

    /**
     * Set important environment variables and re-parse the query string.
     * @return boolean
     */
    function finalize() {
        if (defined('REWRITER_FINALIZED')) return false;

        define('REWRITER_FINALIZED', true);

        if (\is_file($_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_NAME'])) {
            $_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_NAME'];
        }

        if (isset($_SERVER['QUERY_STRING'])) {
            $_GET = [];
            parse_str($_SERVER['QUERY_STRING'], $_GET);
        }

        $_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME'];

        return true;
    }

    /**
     * Adjust the server environment variables to match a given URL.
     * @param string $url
     */
    function set_environment($url) {
        $url = rtrim($url, '&?');
        $request_uri = $script_name = $url;
        $query_string = null;

        if (strpos($url, '?') > 0) {
            $script_name = substr($url, 0, strpos($url, '?'));
            $query_string = substr($url, 1 + strpos($url, '?'));
        }

        $_SERVER['REQUEST_URI'] = $request_uri;
        $_SERVER['SCRIPT_NAME'] = $script_name;
        $_SERVER['QUERY_STRING'] = $query_string;
    }

    /**
     * Parse regular expression matches. eg. $0 or $1
     * @param string $url
     * @return string
     */
    function parse_matches($url) {        
        $replace = function($bit) {
            global $matches;
            return isset($matches[$bit[1]])
                ? $matches[$bit[1]]
                : null;
        };

        return preg_replace_callback('/\$([0-9]+)/', $replace, $url);
    }

    /**
     * Parse Apache style rewrite parameters. eg. %{QUERY_STRING}
     * @param string $url
     * @return string
     */
    function parse_parameters($url) {
        $replace = function($bit) {
            return isset($_SERVER[$bit[1]])
                ? $_SERVER[$bit[1]]
                : null;
        };
        return preg_replace_callback('/%\{([A-Z_+]+)\}/', $replace, $url);
    }

    /**
     * Change the internal url to a different url.
     * @param string $from Regular expression to match current url, or optional when used in conjunction with `test`.
     * @param string $to URL to redirect to.
     * @return boolean
     */
    function rewrite($from, $to = null) {
        if (defined('REWRITER_FINALIZED')) return false;

        $url = $_SERVER['SCRIPT_NAME'];

        if (isset($to)) {
            $url = preg_replace($from, $to, $url);
        } else {
            $url = parse_matches($from);
        }

        set_environment(
            parse_parameters($url)
        );

        return true;
    }

    /**
     * Compare a regular expression against the current request, store the matches for later use.
     * @return boolean
     */
    function test($expression) {
        global $matches;
        if (defined('REWRITER_FINALIZED')) return false;
        return 0 < (integer)preg_match($expression, $_SERVER['SCRIPT_NAME'], $matches);
    }

    initialize();

    // Your rewrite rules here.
    test('%/(.*)-(.*)\.htm$%') && rewrite('/?page=$1&sub=$2&%{QUERY_STRING}') && finalize();
    test('%^([^/]*)\.htm$%') && rewrite('/?page=$0&%{QUERY_STRING}') && finalize();

    echo "<pre>";
    var_dump($_SERVER);
    // include index.php or something

我已经包含了一堆“帮助”函数,这将使您更容易编写重写规则 (borrowed here)。

【讨论】:

  • 让我试试这个...:)
  • 嗨@Bjorn,我在脚本末尾尝试了var_dump($_GET);。它似乎不起作用,或者我想我做错了什么。你能指导和解释我在哪里做什么吗?同时,我也会尝试破译你的剧本!
  • 嗯,什么不工作?如果我运行服务器php -S localhost:8000 router.php,在我的浏览器中打开http://localhost:8000/foo-bar.htm,当我var_dump($_GET) 时我得到page=foo, sub=bar。如果您希望/foo-bar.html?moo 也能正常工作,我发现我在重写时犯了一个小错误。在%{QUERY_STRING} 之前添加&amp; 以修复它。
  • +1 工作伙伴。太感谢了。 :)
【解决方案3】:

我在博客 The Reality Tunnel 上找到了一个教程,该教程引用了 Ripeworks 上的博客,其中包含对我有用的路由器脚本。

他们给出的路由器脚本是

<?php

$root = $_SERVER['DOCUMENT_ROOT'];
chdir($root);
$path = '/'.ltrim(parse_url($_SERVER['REQUEST_URI'])['path'],'/');
set_include_path(get_include_path().':'.__DIR__);
if(file_exists($root.$path))
{
    if(is_dir($root.$path) && substr($path,strlen($path) - 1, 1) !== '/')
        $path = rtrim($path,'/').'/index.php';
    if(strpos($path,'.php') === false) return false;
    else {
        chdir(dirname($root.$path));
        require_once $root.$path;
    }
}else include_once 'index.php';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 2012-07-11
    • 2014-09-25
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多