关于.htaccess和友好url的几个问题


Couple of questions about .htaccess and friendly urls

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

我将首先解释,我的友好的url是如何工作和看起来像。我的语言开关是基于url的,总是包含两个字符。它看起来像这样:stackoverflow.com/en/这使得切换非常容易,因为它基于url。它在SEO方面工作得很好。另外,如果没有设置language-id,那么将使用默认语言(stackoverflow.com/).
)没有以数字表示的页id。我在文本中有唯一的页面id: stackoverflow.com/services.html以及用于SEO和文件夹目录反冲突目的的.html。
对于子页面,我有"$current_page"answers"$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全局空间变量,然后显示它的。htaccess文件?像这样:..^(LANGUAGELISTS)'/.. ?如果这是不可能的,那么下一个最好的事情是匹配该位置的2个字符并将其作为$_GET['language']传递。

我怎么能有无限的父母动态?
意思是,"$parent_page"不是静态设置的,我有无限的孩子,类似于:stackoverflow.com/services/translating/english/somesubpage.html。如果这是可能的,那么,它将如何在php中与数组一起使用?

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

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

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

第二个问题更难……

更新:

在我看来,shhad和topay所说的是一个好的开始。使用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多个艺术家的信息,你想让你的url看起来像website.com/festival/<artistgenre>/<artistname>/。你不想在你的CMS中创建100多个页面,所以<artistgenre><artistname>是某种通配符。

如果没有大量的if/else语句,我发现很难做到这一点,比如:
$item = get_URL_items();    
if(is_user($item[2]) && is_genre($item[1]) && is_festival($item[0])) {
  // do mysql stuff here
}

如果我是你,我会这样写:

. 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中,您可以根据您的需要解析路径

在回答您的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。div =)

我觉得这个答案不会很受欢迎,但不管怎样我还是要说。:)

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

注意事项:

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

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

这是我能找到的关于如何使用PHP做到这一点的唯一教程…

使用MySQL控制mod_rewrite

这与重写的标准方式相距甚远,所以我想我会因为这个答案而受到很多批评。哦。:)

嗯,对于SEO部分,我认为每篇文章最好有slug(参考你使用这个CMS)。意味着在你的数据库中,你有一些"翻译"表,它翻译请求uri/slug并将其与$parent_page相关联。