【问题标题】:Rewrite url with multiple params PHP Apache用多个参数 PHP Apache 重写 url
【发布时间】:2012-11-22 15:59:33
【问题描述】:

我只是花了几个小时在这里四处寻找,但并没有真正找到解决方案。

我目前有典型的查询字符串,例如;

 http://www.site/jobs/results.php?keyword=Accounting+%26+Finance&type=10&state_id=130&location=NSW&order=1&page=1

我想重写哪个

 http://www.site/jobs/find/accounting-finance/NSW/free-jobs/1/?order=1

但我不知道会发送什么参数,这取决于用户的操作、过滤器、类别、订单等

我想保持简单并在 PHP 中解析 url 并使用简单的重写规则,但是我需要键/值对,所以我知道哪个值属于哪个参数之类的;

http://www.site/jobs/find/keyword/accounting-finance/state/NSW/type/free-jobs/page/1/?order=1

有人告诉我,这不是 seo 的好选择。

除了在 .htacces 中编写许多不同的规则以涵盖所有场景之外,您能否提出更好的解决方法

谢谢

【问题讨论】:

    标签: php apache mod-rewrite


    【解决方案1】:

    .htaccess:

    RewriteEngine on
    # skip rewriting if file/dir exists (optionally)
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    # rewrite all to results.php
    RewriteRule . results.php
    

    php(键=>值对的简单方法):

    // current URI (/jobs/find/keyword/accounting-finance/state/NSW/type/free-jobs/page/1/?order=1)
    $path = $_SERVER['REQUEST_URI'];
    
    // remove base path (/jobs)
    if (($len = strlen(basename($_SERVER['SCRIPT_FILENAME'])))) 
        $path = substr($len, $path);
    
    // remove GET params (?order=1)
    if (false !== ($pos = strpos($path, '?'))) 
        $path = substr($path, 0, $pos);
    
    $path = explode('/', trim($path, '/'));
    
    // extract action (or whatever 'find' is)
    $action = array_shift($path);
    
    // make key => value pairs from the rest
    $params = array();
    for ($i = 1, $c = count($path) ; $i < $c ; $i += 2) {
        $params[urldecode($path[$i - 1])] = urldecode($params[$i]);
        // or put it to GET (only remember that it will overwrite already existing values)
        //$_GET[urldecode($path[$i - 1])] = urldecode($params[$i]);
    }
    

    您可以修改此脚本以仅在没有键的情况下实现值,但问题来了 - 是否可以确定值应该是一个键还是另一个?如果参数总是在同一个位置,你只能得到更少或更多的参数,那么它很容易:

    // skip this step from previous example
    //$action = array_shift($path);    
    
    $params = array(
        'action' => null,
        'keyword' => null,
        'state' => null,
        'type' => null,
        'page' => null,
    );
    $keys = array_keys($params);
    for ($i = 0 , $c = min(count($path), count($keys) ; $i < $c ; ++$i) {
        $params[$keys[$i]] = urldecode($path[$i]);
    }
    

    但是如果你不知道哪个参数在哪个位置,那么事情就会变得更加复杂。您需要对每个参数进行一些检查并确定它是哪一个 - 如果所有这些值都是从一些已知的值列表中选择的,那么它也不会很困难,例如:

    $params = array(
        'action' => null,
        'keyword' => null,
        'state' => null,
        'type' => null,
        'page' => null,
    );
    $params['action'] = array_shift($path);
    $keys = array_keys($params);
    foreach ($path as $value) {
        if (is_numeric($value)) $params['page'] = intVal($value);
        else {
            $key = null;
            // that switch is not very nice - because of hardcode
            // but is much faster than using 'in_array' or something similar
            // anyway it can be done in many many ways
            switch ($value) {
                case 'accounting-finance' :
                case 'keyword2' :
                case 'keyword3' :
                    $key = 'keyword';
                    break;
                case 'NSW' :
                case 'state2' :
                    $key = 'state';
                    break;
                case 'type1' :
                case 'type2' :
                case 'type3' :
                    $key = 'type';
                    break;
                // and so on...
            }
            if ($key === null) throw new Exception('Unknown value!');
            $params[$key] = $value;
        }
    }
    

    您也可以尝试在 .htaccess 中编写一些非常复杂的正则表达式,但 IMO 不是这样的地方 - apache 应该在您的应用程序中将请求与正确的端点匹配并运行它,它不是扩展参数逻辑的地方(如果无论如何,它将转到您应用程序中的同一位置)。在应用程序中保留该逻辑也更方便 - 当您更改某些内容时,您可以在应用程序代码中执行此操作,而无需更改 htaccess 或 apache 配置中的任何内容(在生产环境中,我主要将 .htaccess 内容移动到 apache 配置并关闭 .htaccess 支持 - 当 apache 不搜索这些文件时,这会加快速度,但任何更改都需要重新启动 apache。

    【讨论】:

    • 这就是想法,但是如何在没有键/值对的情况下做到这一点呢?我真的想要 find/value/value/value/ 例如 find/accounting-finance/NSW/free-jobs/1/
    • 我认为答案是使用 rewrite 将参数转换为 url 并通过 GET 发送原始查询字符串值进行解析。我必须为每个参数写一个规则,但没关系。
    • 我宁愿将它传递给 PHP 并在那里解析。在$action = array_shift($path); 之后,您有来自 url 的参数列表,您可以随心所欲地使用它 - 我描述了如何制作 key=>value 对,但我可以轻松地将其更改为参数解析(没有键)。另一种选择是为整个路径(在爆炸之前)编写一些正则表达式规则并以这种方式进行。
    • 感谢 lupatus,我设置了一些测试,发现使用反向引用会变得非常棘手,因为 id 必须先使用某种重定向或解析整个内容,所以我认为你的方法是最容易实现的。
    • 本质上正如您所指出的,主要问题是匹配参数,因为它们会有所不同并且并不总是处于相同的位置。再次感谢您的宝贵时间。
    【解决方案2】:

    如果您只想将任何与 SEO 相关的内容推送到 URL 中,那么您的重写实际上变得非常容易:根本不进行任何重写,将参数保留在原处,只需在 @ 后面填满987654321@ 与您的 SEO 关键字:

    http://myurl/jobs/results.php/seo-keywords/gohere/as-you-like-it?keyword=Accounting+%26+Finance&type=10&state_id=130&location=NSW&order=1&page=1
    

    它应该不会对 PHP 产生影响,因为这个不存在的路径最终会被解析为 $_SERVER['PATH_INFO'],但脚本执行保持不变。

    现在的问题是:您的 SEO 相关关键字的来源是什么? :)

    【讨论】:

    • 这是一种选择,但不是我所追求的。
    猜你喜欢
    • 2017-02-03
    • 2015-12-06
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    • 1970-01-01
    • 2011-03-17
    相关资源
    最近更新 更多