【问题标题】:Couple of questions about .htaccess and friendly urls关于 .htaccess 和友好网址的几个问题
【发布时间】:2011-08-18 03:59:52
【问题描述】:

我一直不擅长 apache,并且使用了非常简单的解决方案。现在我已经构建了一个 cms 软件.. 但是 .htaccess 开始大幅缩减。

我将首先解释我的友好网址的工作方式和外观。我的语言切换是基于 url 的,并且总是包含两个字符。它看起来像这样:stackoverflow.com/en/ 这使得切换非常容易,因为它基于 url.. 它在 SEO 术语中运行良好。此外,如果未设置语言 ID,则将使用默认语言 (stackoverflow.com/)。
数字中没有页面 ID。我在文本中有唯一的页面 ID:stackoverflow.com/services.html,最后用于 SEO 和文件夹目录反冲突目的 .html..
对于子页面,我有“$current_page”和“$parent_page”样式变量:stackoverflow.com/services/translating.html 服务是父页面,翻译是当前页面。
还有一些示例代码(我对它进行了很多削弱,所以你不会认为它不完整):

RewriteRule ^(et|en|fi)\/(.+)\/(.+)\.html  index.php?language=$1&pagelink=$3&parentlink=$2 [L,NC,QSA]

RewriteRule ^(.+)\/(.+)\.html  index.php?language=0&pagelink=$2&parentlink=$1 [L,NC,QSA]
RewriteRule ^(.+)\.html  index.php?language=0&pagelink=$1&parentlink=0 [L,NC,QSA]

如何使语言切换部分更加动态?
这个方法..^(et|en|fi)\/..意味着,当我设置cms时,我必须手动设置语言列表。最好的办法是从 cms 设置中以某种方式设置它。因为,这种方式不存在与文件夹相关的冲突。是否可以通过 php 全局 apace 变量,然后将其显示为 .htaccess 文件?像这样的东西:..^(LANGUAGELISTS)\/..?如果这是不可能的,那么下一个最好的办法是匹配该位置的 2 个字符并将其作为 $_GET['language'] 传递。

如何动态拥有无限的父母?
意思是,“$parent_page”不是静态设置的,我有无限的孩子​​,类似于:stackoverflow.com/services/translating/english/somesubpage.html。如果可以的话,那么如何在 php 中使用数组呢?

赏金编辑
问题的第一部分基本解决了,除非有人想出一些 php -> apache-array -> .htaccess 方式。
但是,问题的第二部分仍然没有解决。由于这是我所有项目的问题,并且将来可能会帮助其他人,因此我决定为这个问题添加赏金。

【问题讨论】:

    标签: php apache .htaccess friendly-url seo


    【解决方案1】:

    回答您的第一个问题: 你可以使用RewriteRule ^([a-zA-Z]{2})([/]?)(.*)$ path/file.php?language=$1 这会将第一个字符串限制为两个字符并将其传递给$_GET['language']

    编辑:添加RewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-d 将防止与现有目录/文件发生冲突

    第二个问题要困难得多..

    更新:

    在我看来,Shad 和 toopay 所说的是一个好的开始。 使用explode() 分隔级别并将其与slug 进行比较非常简单。 但是,一旦您想为脚本添加灵活性,它就会变得复杂。

    function get_URL_items() {
    $get_URL_items_url = $_SERVER['REQUEST_URI'];
    $get_URL_items_vars = explode("/",$get_URL_items_url);
    for ($get_URL_items_i = 0; $get_URL_items_i < count($get_URL_items_vars) ; $get_URL_items_i++) {
        if(strlen(trim($get_URL_items_vars[$get_URL_items_i])) == 0) {
            unset($get_URL_items_vars[$get_URL_items_i]);
        }
    }
    return $get_URL_items_vars;
    

    假设您有一个网站,其中包含一个名为“音乐节”的子版块和一个包含 100 多位艺术家信息的数据库,并且您希望您的网址看起来像 website.com/festival/&lt;artistgenre&gt;/&lt;artistname&gt;/。 您不想在 CMS 中创建 100 多个页面,因此 &lt;artistgenre&gt;&lt;artistname&gt; 是某种通配符。

    如果没有很多 if/else 语句,我发现很难实现这一点:

    $item = get_URL_items();    
    if(is_user($item[2]) && is_genre($item[1]) && is_festival($item[0])) {
      // do mysql stuff here
    }
    

    【讨论】:

    • 回答您的问题。这似乎确实有效,但是如果有一个文件夹 in/ 与 .htaccess 文件在同一目录中有两个字符,它不会发生冲突吗?
    • 我做到了。如果没有“通过 php 的全局 apache 数组”功能,那么这就是最好和完美的答案。但是,我目前正计划为这个问题增加赏金以解决第二部分。所以正如我所说,当没有 php 到 apache 的方法时,你会得到接受,并且得到正确的无限父母问题的人将获得赏金。所以基本上谢谢!你完美地回答了第一部分:)
    【解决方案2】:

    如果我是你,我会使用这样的东西:

    .htaccess:

    Options +FollowSymLinks
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !/main.php$
    RewriteRule ^([a-zA-Z]{2})?(.*)$ main.php?lang=$1&path=$2 [L,QSA]
    

    main.php:

    $langs = array('en','de','ru'); // list of supported languages
    $currentLang = isset($_GET['lang'])&&in_array($_GET['lang']) ? $_GET['lang'] : $defaultLang; // current selected language
    $path = $_GET['path']; // current path
    

    然后,在 main.php 中你可以根据需要解析路径

    【讨论】:

    • 这似乎与 Thomas GG 的答案非常相似。 php 部分目前不是主题。默认语言检查//回退已经生效。但是我不明白你的意思,为什么我在 .htaccess 中有(et|en|fi)。所以谢谢你的指点。
    【解决方案3】:

    在回答您的bounty 问题时,我会使用这个:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^([A-Z]{2}\/)*(([A-Z]+\/)*)([A-Z]+)\.html$ index.php?lang=$1&parents=$2&pagelink=$4 [NC,QSA,L]
    

    既然您希望能够在您的 URL 中处理任意数量的世代/级别,您是否考虑过您希望如何在 PHP 脚本中捕获它们?

    你肯定不想去检查isset($_GET['parent1']);isset($_GET['parent2'])等等等等等等。

    正如其他一些回复所表明的,您确实需要在 PHP 脚本中解析您的 URL;为此,我的 RewriteRule 将 URL 的整个“父母”部分移交给您,然后您的脚本可以explode 并对其进行解析;但不会干扰正常的无父 URL。 =)

    【讨论】:

      【解决方案4】:

      我不知何故认为这个答案不会很受欢迎,但无论如何都可以。 :)

      mod_rewrite 达到了一个地步,使用正则表达式的老式方式变得烦人。我建议您跳过所有的痛苦,转而使用外部程序/脚本进行重写。我不建议您使用这种方法重写所有文件,而只建议大多数用户会看到和输入的 url。只要你知道如何编写高效的代码,你甚至可以重定向到一个 php 脚本来进行重写(就像我过去在一个非常高流量的网站上所做的那样),它不会对加载时间产生明显的影响。如果您曾经达到重写是减慢网站速度的主要原因,那么您可以将其切换为用更快的语言编写的程序,但是如果您达到了这一点,我会感到惊讶。

      一些注意事项:

      • 您需要设置一个重写锁定指令,否则您会得到很多疯狂的输出。
      • 请记住,重写脚本是一个命令行 PHP 脚本。它不知道诸如 $_SERVER 全局之类的东西。这很容易忘记。
      • 此脚本在服务器启动时加载,因此对其进行的任何更改都需要重新启动服务器才能生效。
      • 始终在命令行上通过传递 url 并在重新启动服务器之前检查输出来对此进行测试。如果您的脚本损坏,重新启动服务器将导致从无法正常重写到服务器根本无法启动的任何事情。

      一开始有点麻烦,但是一旦你设置好了,你会发现添加新的重写规则绝对是一件轻而易举的事情,而且更加灵活。

      这是我能找到的关于如何使用 PHP 执行此操作的唯一教程...

      Using MySQL to control mod_rewrite via PHP

      这与进行重写的标准方式相去甚远,所以我想我会为这个答案付出很多。那好吧。 :)

      【讨论】:

      • 非常非常有趣的概念。但是服务器的变化是不确定的,因为我正在寻找一个 cms 软件的解决方案。尽管如此,这可以在安装时自动完成。它可能会给用户带来很大的问题。但是,这仍然非常有趣。
      • 我明白了,我以为您控制着 CMS 服务器并使用它来开发网站。我没有意识到你会分发 CMS。您始终可以将其设置为仅在当前请求与某个域或路径匹配时才使用您的重写脚本。此外,大多数 Linux 发行版都有一个用于 Apache 的 conf.d 目录,您只需将 rewrite conf 脚本添加到该目录即可,而无需对主要 apache 配置文件进行任何解析。
      【解决方案5】:

      好吧,对于SEO 部分,我认为最好为每篇文章使用slug(参考您将其用于CMS)。意味着在您的数据库中,您有一些“翻译”表,可以翻译请求的 uri/slug 并将其与 $parent_page 关联。

      【讨论】:

        猜你喜欢
        • 2013-03-20
        • 2010-10-24
        • 2016-02-02
        • 2012-10-15
        • 2016-03-11
        • 2017-05-14
        • 2014-07-26
        • 2012-04-27
        • 2012-08-14
        相关资源
        最近更新 更多