用 PHP 重写 URL
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16388959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
URL rewriting with PHP
提问by Jazerix
I have a URL that looks like:
我有一个看起来像的 URL:
url.com/picture.php?id=51
How would I go about converting that URL to:
我将如何将该 URL 转换为:
picture.php/Some-text-goes-here/51
I think WordPress does the same.
我认为 WordPress 也是如此。
How do I go about making friendly URLs in PHP?
如何在 PHP 中制作友好的 URL?
回答by Niels Keurentjes
You can essentially do this 2 ways:
您基本上可以通过两种方式执行此操作:
The .htaccess route with mod_rewrite
带有 mod_rewrite 的 .htaccess 路由
Add a file called .htaccess
in your root folder, and add something like this:
.htaccess
在根文件夹中添加一个名为的文件,然后添加如下内容:
RewriteEngine on
RewriteRule ^/?Some-text-goes-here/([0-9]+)$ /picture.php?id=
This will tell Apache to enable mod_rewrite for this folder, and if it gets asked a URL matching the regular expression it rewrites it internallyto what you want, without the end user seeing it. Easy, but inflexible, so if you need more power:
这将告诉 Apache 为这个文件夹启用 mod_rewrite,如果它被询问匹配正则表达式的 URL,它会在内部将其重写为您想要的内容,而最终用户不会看到它。简单但不灵活,因此如果您需要更多功能:
The PHP route
PHP路线
Put the following in your .htaccess instead: (note the leading slash)
将以下内容放在您的 .htaccess 中:(注意前导斜杠)
FallbackResource /index.php
This will tell it to run your index.php
for all files it cannot normally find in your site. In there you can then for example:
这将告诉它运行您index.php
的所有文件,它通常无法在您的站点中找到。在那里你可以例如:
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
if(empty($elements[0])) { // No path elements means home
ShowHomepage();
} else switch(array_shift($elements)) // Pop off first item and switch
{
case 'Some-text-goes-here':
ShowPicture($elements); // passes rest of parameters to internal function
break;
case 'more':
...
default:
header('HTTP/1.1 404 Not Found');
Show404Error();
}
This is how big sites and CMS-systems do it, because it allows far more flexibility in parsing URLs, config and database dependent URLs etc. For sporadic usage the hardcoded rewrite rules in .htaccess
will do fine though.
这就是大型站点和 CMS 系统的做法,因为它在解析 URL、配置和数据库相关 URL 等方面提供了更大的灵活性。对于零星的使用,硬编码的重写规则.htaccess
虽然很好。
回答by Danijel
If you only want to change the route for picture.php
then adding rewrite rule in .htaccess
will serve your needs, but, if you want the URL rewriting as in Wordpress then PHP is the way. Here is simple example to begin with.
如果您只想更改路由,picture.php
然后在其中添加重写规则.htaccess
将满足您的需求,但是,如果您想像 Wordpress 中那样重写 URL,那么 PHP 就是方法。下面是一个简单的例子。
Folder structure
文件夹结构
There are two files that are needed in the root folder, .htaccess
and index.php
, and it would be good to place the rest of the .php
files in separate folder, like inc/
.
根文件夹中需要两个文件.htaccess
和index.php
,最好将其余.php
文件放在单独的文件夹中,例如inc/
.
root/
inc/
.htaccess
index.php
.htaccess
.htaccess
RewriteEngine On
RewriteRule ^inc/.*$ index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
This file has four directives:
这个文件有四个指令:
RewriteEngine
- enable the rewriting engineRewriteRule
- deny access to all files ininc/
folder, redirect any call to that folder toindex.php
RewriteCond
- allow direct access to all other files ( like images, css or scripts )RewriteRule
- redirect anything else toindex.php
RewriteEngine
- 启用重写引擎RewriteRule
- 拒绝访问文件inc/
夹中的所有文件,将对该文件夹的任何调用重定向到index.php
RewriteCond
- 允许直接访问所有其他文件(如图像、CSS 或脚本)RewriteRule
- 将其他任何内容重定向到index.php
index.php
索引.php
Because everything is now redirected to index.php, there will be determined if the url is correct, all parameters are present, and if the type of parameters are correct.
因为现在一切都被重定向到 index.php,所以将确定 url 是否正确,所有参数是否存在,以及参数类型是否正确。
To test the url we need to have a set of rules, and the best tool for that is a regular expression. By using regular expressions we will kill two flies with one blow. Url, to pass this test must have all the required parameters that are tested on allowed characters. Here are some examples of rules.
要测试 url,我们需要有一组规则,而最好的工具是正则表达式。通过使用正则表达式,我们将一击杀死两只苍蝇。Url,要通过此测试,必须具有对允许的字符进行测试的所有必需参数。以下是一些规则示例。
$rules = array(
'picture' => "/picture/(?'text'[^/]+)/(?'id'\d+)", // '/picture/some-text/51'
'album' => "/album/(?'album'[\w\-]+)", // '/album/album-slug'
'category' => "/category/(?'category'[\w\-]+)", // '/category/category-slug'
'page' => "/page/(?'page'about|contact)", // '/page/about', '/page/contact'
'post' => "/(?'post'[\w\-]+)", // '/post-slug'
'home' => "/" // '/'
);
Next is to prepare the request uri.
接下来是准备请求uri。
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
Now that we have the request uri, the final step is to test uri on regular expression rules.
现在我们有了请求 uri,最后一步是在正则表达式规则上测试 uri。
foreach ( $rules as $action => $rule ) {
if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
/* now you know the action and parameters so you can
* include appropriate template file ( or proceed in some other way )
*/
}
}
Successful match will, since we use named subpatterns in regex, fill the $params
array almost the same as PHP fills the $_GET
array. However, when using a dynamic url, $_GET
array is populated without any checks of the parameters.
成功的匹配将,因为我们在正则表达式中使用命名子模式,填充$params
数组几乎与 PHP 填充$_GET
数组相同。但是,当使用动态 url 时,$_GET
会在不检查任何参数的情况下填充数组。
/picture/some+text/51 Array ( [0] => /picture/some text/51 [text] => some text [1] => some text [id] => 51 [2] => 51 ) picture.php?text=some+text&id=51 Array ( [text] => some text [id] => 51 )
These few lines of code and a basic knowing of regular expressions is enough to start building a solid routing system.
这几行代码和对正则表达式的基本了解足以开始构建一个可靠的路由系统。
Complete source
完整的源码
define( 'INCLUDE_DIR', dirname( __FILE__ ) . '/inc/' );
$rules = array(
'picture' => "/picture/(?'text'[^/]+)/(?'id'\d+)", // '/picture/some-text/51'
'album' => "/album/(?'album'[\w\-]+)", // '/album/album-slug'
'category' => "/category/(?'category'[\w\-]+)", // '/category/category-slug'
'page' => "/page/(?'page'about|contact)", // '/page/about', '/page/contact'
'post' => "/(?'post'[\w\-]+)", // '/post-slug'
'home' => "/" // '/'
);
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
foreach ( $rules as $action => $rule ) {
if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
/* now you know the action and parameters so you can
* include appropriate template file ( or proceed in some other way )
*/
include( INCLUDE_DIR . $action . '.php' );
// exit to avoid the 404 message
exit();
}
}
// nothing is found so handle the 404 error
include( INCLUDE_DIR . '404.php' );
回答by Luca Rocchi
this is an .htaccess file that forward almost all to index.php
这是一个 .htaccess 文件,几乎将所有内容转发到 index.php
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !-l
RewriteCond %{REQUEST_FILENAME} !\.(ico|css|png|jpg|gif|js)$ [NC]
# otherwise forward it to index.php
RewriteRule . index.php
then is up to you parse $_SERVER["REQUEST_URI"] and route to picture.php or whatever
然后取决于您解析 $_SERVER["REQUEST_URI"] 并路由到 picture.php 或其他任何内容
回答by rauchmelder
PHP is not what you are looking for, check out mod_rewrite
PHP 不是您要找的,请查看mod_rewrite
回答by Abhishek Gurjar
Although already answered, and author's intent is to create a front controller type app but I am posting literal rule for problem asked. if someone having the problem for same.
虽然已经回答,作者的意图是创建一个前端控制器类型的应用程序,但我发布了针对问题的文字规则。如果有人有同样的问题。
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([\d]+)$ ?id= [L]
Above should work for url picture.php/Some-text-goes-here/51
. without using a index.php as a redirect app.
以上应该适用于 url picture.php/Some-text-goes-here/51
。不使用 index.php 作为重定向应用程序。