我有一个网址,看起来像:
url.com/picture.php?id=51
我将如何将该URL转换为:
picture.php/Some-text-goes-here/51
我认为WordPress也是一样。
如何使用PHP创建友好的URL?
mod_rewrite
就是您所需要的,SO上对此有很多疑问。而且,如果您“认为” wordpress的功能相同,为什么不简单地查找它呢?;)
我有一个网址,看起来像:
url.com/picture.php?id=51
我将如何将该URL转换为:
picture.php/Some-text-goes-here/51
我认为WordPress也是一样。
如何使用PHP创建友好的URL?
mod_rewrite
就是您所需要的,SO上对此有很多疑问。而且,如果您“认为” wordpress的功能相同,为什么不简单地查找它呢?;)
Answers:
您基本上可以通过以下两种方式执行此操作:
.htaccess
在您的根文件夹中添加一个名为的文件,并添加如下内容:
RewriteEngine on
RewriteRule ^/?Some-text-goes-here/([0-9]+)$ /picture.php?id=$1
这将告诉Apache为该文件夹启用mod_rewrite,如果询问它与正则表达式匹配的URL,它将在内部将其重写为所需的内容,而最终用户看不到它。简单但不灵活,因此,如果您需要更多功能:
将以下内容放在您的.htaccess文件中:(请注意斜杠)
FallbackResource /index.php
这将告诉它为您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();
}
这是大型站点和CMS系统执行此操作的方法,因为它在解析URL,配置和数据库相关的URL等方面提供了更大的灵活性。对于零星使用,硬编码的重写规则.htaccess
可以很好地工作。
picture.php/invalid-text/51
也将重定向到相同的位置。您还可以添加检查以查看字符串是否正确,如果不正确,请再次重定向到正确的位置。这就是我在使用htaccess的网站上做到这一点的方式。
/blog/25
,以及/picture/51
和/download/684
。此外,它被认为是非常糟糕的做法(让你谷歌PR处罚!)如果不是全部随机生成的URL正确返回404
FallbackResource /index.php
(请注意斜线)
FallbackResource
仅启动文件系统上实际不存在的文件,因此回退。因此,如果您有一个文件/static/styles.css
并由于http://mydomain.tld/static/styles.css
从未执行过代码而将其引用,则可以使其按预期和透明地工作。
if($elements[0] === NULL)
改用它,因为$elements
即使它为空,它仍将返回一个计数1。
如果只想更改路由,picture.php
则添加重写规则.htaccess
将满足您的需求,但是,如果您希望像Wordpress中那样重写URL,则可以使用PHP。这是一个简单的例子。
资料夹结构
根文件夹(.htaccess
和)中需要两个文件,index.php
最好将其余.php
文件放在单独的文件夹中,例如inc/
。
root/
inc/
.htaccess
index.php
.htaccess
RewriteEngine On
RewriteRule ^inc/.*$ index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
该文件有四个指令:
RewriteEngine
-启用重写引擎RewriteRule
-拒绝访问文件inc/
夹中的所有文件,将对该文件夹的任何调用重定向到index.php
RewriteCond
-允许直接访问所有其他文件(例如图像,CSS或脚本)RewriteRule
-将其他任何内容重定向到 index.php
index.php
因为现在所有内容都重定向到index.php,所以将确定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' => "/" // '/'
);
接下来是准备请求uri。
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
现在我们有了请求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 )
*/
}
}
由于我们在正则表达式中使用命名子模式,因此成功匹配将填充$params
数组,几乎与PHP填充$_GET
数组相同。但是,使用动态URL时,$_GET
将在不检查参数的情况下填充数组。
/ picture / some + text / 51 数组 ( [0] => / picture / some text / 51 [文字] =>一些文字 [1] =>一些文字 [id] => 51 [2] => 51 ) picture.php?text = some + text&id = 51 数组 ( [文字] =>一些文字 [id] => 51 )
这几行代码和对正则表达式的基本了解足以开始构建可靠的路由系统。
完整资料
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' );
这是一个.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
然后由您来解析$ _SERVER [“ REQUEST_URI”]并路由到picture.php或任何其他内容
FallbackResource
早在几个主要版本中就引入了该指令,由于它不需要启动整个重写引擎,因此现在是以较低的性能成本实现此行为的首选方法。文档在这里。您的规则也有缺陷,因为您没有引用目录(!-d
)并且所有扩展名过滤器都已过时- -f
应该已经捕获了它们。
尽管已经回答了,并且作者的意图是创建一个前端控制器类型的应用程序,但是我正在针对所问的问题发布文字规则。如果有人有同样的问题。
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([\d]+)$ $1?id=$3 [L]
以上应该适用于url picture.php/Some-text-goes-here/51
。而不使用index.php作为重定向应用。