使用.htaccess文件如何进行RewriteRule/RewriteCond,不涉及文件名?

huangapple go评论63阅读模式
英文:

Using htaccess how do I RewriteRule/RewriteCond with no filename?

问题

不要有别的内容,只翻译代码部分:

Hoping this isn't a duplicate, done a lot of looking and I just get more confused as I don't use `.htaccess` often.

I would like to have some pretty URLs and see lots of help regarding getting information where for example `index.php` is passed a parameter such as `page`. So I can currently convert `www.example.com/index.php?page=help` to `www.example.com/help`.

Obviously I'm not clued up on this but I would like to parse a URL such as `www.example.com/?page=help`.

Can't seem to find much info and adapting the original I am obviously going wrong somewhere.

Any help or pointers in the right direction would be greatly appreciated. I'm sure its probably stupidly simple.

My alterations so far which do not seem to work are:

RewriteCond %{THE_REQUEST} ^.*/?page=$1
RewriteRule ^(.*)/+page$ /$1[QSA,L]

Also recently tried `QUERY_STRING` but just getting server error.

RewriteCond %{QUERY_STRING} ^page=([a-zA-Z]*)
RewriteRule ^(.*) /$1 [QSA,L]

Given up as dead to the world so thought I would ask. Hoping to ensure the request/url etc starts `?page` and wanting to make a clean URL from the `page` parameter.
英文:

Hoping this isn't a duplicate, done a lot of looking and I just get more confused as I don't use .htaccess often.

I would like to have some pretty URLs and see lots of help regarding getting information where for example index.php is passed a parameter such as page. So I can currently convert www.example.com/index.php?page=help to www.example.com/help.

Obviously I'm not clued up on this but I would like to parse a URL such as www.example.com/?page=help.

Can't seem to find much info and adapting the original I am obviously going wrong somewhere.

Any help or pointers in the right direction would be greatly appreciated. I'm sure its probably stupidly simple.

My alterations so far which do not seem to work are:

RewriteCond %{THE_REQUEST} ^.*/?page=$1
RewriteRule ^(.*)/+page$ /$1[QSA,L]

Also recently tried QUERY_STRING but just getting server error.

RewriteCond %{QUERY_STRING} ^page=([a-zA-Z]*)
RewriteRule ^(.*) /$1 [QSA,L]

Given up as dead to the world so thought I would ask. Hoping to ensure the request/url etc starts ?page and wanting to make a clean URL from the page parameter.

答案1

得分: 0

RewriteCond %{QUERY_STRING} ^page=([^&]+)
RewriteRule ^$ /%1? [R=302,L]

Can't delete and didn't want to waste anyone's time responding.

英文:
RewriteCond %{QUERY_STRING} ^page=([^&]+)
RewriteRule ^$ /%1? [R=302,L]

Can't delete and didn't want to waste anyones time responding.

答案2

得分: 0

这是整个/基本的过程...

1. HTML源代码

确保在你的HTML源代码中链接到“美观/规范”的URL。这应该是以斜杠(或绝对路径)开头的根相对URL,以防以后从不同的URL路径深度重写。例如:

<a href="/help">帮助页面</a>

2. 重写“美观”URL

.htaccess文件中(使用mod_rewrite),将“美观”URL内部重写到实际处理请求的文件,即“前端控制器”(例如index.php),如果需要的话,传递page URL参数。例如:

DirectoryIndex index.php

RewriteEngine On

# 将形如"/help"的URL重写为"index.php?page=help"
RewriteRule ^[^.]+$ index.php?page=$0 [L]

RewriteRule中的模式^[^.]+$匹配任何不包含点的URL路径。通过排除点,我们可以轻松地省略映射到物理文件的任何请求(包含点分隔的文件扩展名)。

$0反向引用包含被RewriteRule模式匹配的整个URL路径。

DirectoryIndex是在请求“主页”(根目录)时所需的,当URL路径为空时。在这种情况下,不会将page URL参数传递给我们的脚本。

3. 实现前端控制器/路由(即index.php

index.php(您的“前端控制器”/路由)中读取page URL参数并提供适当的内容。例如:

<?php
$pages = [
    'home' => '/content/homepage.php',
    'help' => '/content/help-page.php',
    'about' => '/content/about-page.php',
    '404' => '/content/404.php',
];

// 如果省略了"page" URL参数或为空,则默认为"home"
$page = empty($_GET['page']) ? 'home' : $_GET['page'];

// 如果在页面数组/数据库中找不到,则默认为404 "page"
$handler = $pages[$page] ?? $pages['404'];
include($_SERVER['DOCUMENT_ROOT'].$handler);

如上所示,实际的“内容”存储在/content子目录中。通过将这些文件存储在单独的目录中,可以轻松地防止直接访问。

4. 重定向“旧/丑陋”URL到“新/美观”URL【可选】

这仅在您正在更改现有URL结构并且“旧/丑陋”(原始)URL已经暴露(由搜索引擎索引,由第三方链接等)时才是绝对必要的(以保护SEO),否则“旧”URL(即/index.php?page=abc)是可访问的。这与每当您更改现有URL结构时都是一样的。

如果网站是新的,并且您从一开始就实现“新/美观”的URL,则这并不那么重要,但它可以防止用户访问旧URL,如果它们曾经被暴露或被猜测。

以下内容应放在内部重写之前,以及RewriteEngine指令之后。例如:

# 将形如"/index.php?page=help"的“旧”URL重定向到“/help”
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/index\.php$ [OR]
RewriteCond %{QUERY_STRING} ^page=([^.&]*)
RewriteRule ^(index\.php)?$ /%1 [R=301,L]

REDIRECT_STATUS环境变量的检查通过不重定向已被后来的重写重写的请求,以防止重定向循环。

%1反向引用包含page URL参数的值,从前面的CondPatternRewriteCond指令)中捕获。请注意,这与上面的重写中使用的$n反向引用不同。

以上内容重定向了所有URL变种,包括有/没有index.php和有/没有page URL参数的情况。例如:

  • /index.php?page=help -> /help
  • /?page=help -> /help
  • /index.php -> /(主页)
  • /?page= -> /(主页)

提示:首先使用302(临时)重定向进行测试,以防止潜在的缓存问题。

英文:

<!--
I'm not sure which bit specifically you are stuck on, since you say you can convert example.com/index.php?page=help to www.example.com/help, but anyway,
-->

This is the whole/basic process...

1. HTML Source

Make sure you are linking to the "pretty/canonical" URL in your HTML source. This should be a root-relative URL starting with a slash (or absolute), in case you rewrite from different URL path depths later. For example:

&lt;a href=&quot;/help&quot;&gt;Help Page&lt;/a&gt;

2. Rewrite the "pretty" URL

In .htaccess (using mod_rewrite), internally rewrite the "pretty" URL back to the file that actually handles the request, ie. the "front-controller" (eg. index.php, passing the page URL parameter if you wish). For example:

DirectoryIndex index.php

RewriteEngine On

# Rewrite URL of the form &quot;/help&quot; to &quot;index.php?page=help&quot;
RewriteRule ^[^.]+$ index.php?page=$0 [L]

The RewriteRule pattern ^[^.]+$ matches any URL-path that does not include a dot. By excluding a dot we can easily omit any request that would map to a physical file (that includes a file extension delimited by a dot).

The $0 backreference contains the entire URL-path that is matched by the RewriteRule pattern.

The DirectoryIndex is required when the "homepage" (root-directory) is requested, when the URL-path is otherwise empty. In this case the page URL parameter is not passed to our script.

3. Implement the front-controller / router (ie. index.php)

In index.php (your "front-controller" / router) we read the page URL parameter and serve the appropriate content. For example:

&lt;?php
$pages = [
    &#39;home&#39; =&gt; &#39;/content/homepage.php&#39;,
    &#39;help&#39; =&gt; &#39;/content/help-page.php&#39;,
    &#39;about&#39; =&gt; &#39;/content/about-page.php&#39;,
    &#39;404&#39; =&gt; &#39;/content/404.php&#39;,
];

// Default to &quot;home&quot; if &quot;page&quot; URL param is omitted or is empty
$page = empty($_GET[&#39;page&#39;]) ? &#39;home&#39; : $_GET[&#39;page&#39;];

// Default to 404 &quot;page&quot; if not found in the array/DB of pages
$handler = $pages[$page] ?? $pages[&#39;404&#39;];
include($_SERVER[&#39;DOCUMENT_ROOT&#39;].$handler);

As seen in the above script, the actual "content" is stored in the /content subdirectory. (This could also be a location outside of the document root.) By storing these files in a separate directory they can be easily protected from direct access.

4. Redirect the "old/ugly" URL to the "new/pretty" URL [OPTIONAL]

This is only strictly necessary (in order to preserve SEO) if you are changing an existing URL structure and the "old/ugly" (original) URLs have been exposed (indexed by search engines, linked to by third parties, etc.), otherwise the "old" URL (ie. /index.php?page=abc) is accessible. This is the same whenever you change an existing URL structure.

If the site is new and you are implementing the "new/pretty" URLs from the start then this is not so important, but it does prevent users from accessing the old URLs if they were ever exposed/guessed.

The following would go before the internal rewrite and after the RewriteEngine directive. For example:

# Redirect &quot;old&quot; URL of the form &quot;/index.php?page=help&quot; to &quot;/help&quot;
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/index\.php$ [OR]
RewriteCond %{QUERY_STRING} ^page=([^.&amp;]*)
RewriteRule ^(index\.php)?$ /%1 [R=301,L]

The check against the REDIRECT_STATUS environment variable prevents a redirect-loop by not redirecting requests that have already been rewritten by the later rewrite.

The %1 backreference contains the value of the page URL parameter, as captured from the preceding CondPattern (RewriteCond directive). (Note how this is different to the $n backreference as used in the rewrite above.)

The above redirects all URL variants both with/without index.php and with/without the page URL parameter. For example:

  • /index.php?page=help -> /help
  • /?page=help -> /help
  • /index.php -> / (homepage)
  • /?page= -> / (homepage)

TIP: Test first with 302 (temporary) redirects to prevent potential caching issues.

Comments / improvements / Exercises for the reader

  • The above does not handle additional URL parameters. You can use the QSA (Query String Append) flag on the initial rewrite to append additional URL parameters on the initially requested URL. However, implementing the reverse redirect is not so trivial.

  • You don't need to pass the page URL parameter in the rewrite. The entire (original) URL is available in the PHP superglobal $_SERVER[&#39;REQUEST_URI&#39;] (which also includes the query string - if any). You can then parse this variable to extract the required part of the URL instead of relying on the page URL parameter. This generally allows greatest flexibility, without having to modify .htaccess later.

    However, being able to pass a page URL parameter can be "useful" if you ever want to manually rewrite (override) a URL route using .htaccess.

  • Incorporate regex (wildcard pattern matching) in the "router" script so you can generate URLs with "parameters". eg. /&lt;page&gt;/&lt;param1&gt;/&lt;param2&gt; like /photo/cat/large.

Reference:

huangapple
  • 本文由 发表于 2023年2月18日 08:29:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75490378.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定