用 PHP 重写 URL

我有一个网址,看起来像:

url.com/picture.php?id=51

我该如何将这个 URL 转换为:

picture.php/Some-text-goes-here/51

我认为 WordPress 也是如此。

如何在 PHP 中创建友好的 URL?

295432 次浏览

PHP 不是你要找的,看看 改写

你可以通过两种方式来实现:

使用 mod _ rewrite 的. htaccess 路由

在根文件夹中添加一个名为 .htaccess的文件,并添加如下内容:

RewriteEngine on
RewriteRule ^/?Some-text-goes-here/([0-9]+)$ /picture.php?id=$1

这将告诉 Apache 为这个文件夹启用 mod _ rewrite,如果它收到匹配正则表达式的 URL 请求,它将把它重写为您想要的 在内部,而最终用户看不到它。简单,但不灵活,所以如果你需要更多的电力:

PHP 路线

把以下内容放在.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中的硬编码重写规则可以做得很好。

这是一个. 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 或其他

如果你只是想改变 picture.php的路由,那么在 .htaccess中添加重写规则就可以满足你的需要,但是,如果你想要像 Wordpress 一样重写 URL,那么 PHP 就是最好的方法。下面是一个简单的例子。

文件夹结构

根文件夹中需要两个文件 .htaccessindex.php,最好将其余的 .php文件放在单独的文件夹中,如 inc/

root/
inc/
.htaccess
index.php

. htaccess

RewriteEngine On
RewriteRule ^inc/.*$ index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]

这个文件有四个指令:

  1. 启用重写引擎
  2. 拒绝访问 inc/文件夹中的所有文件,将对该文件夹的任何调用重定向到 index.php
  3. RewriteCond-允许直接访问所有其他文件(如图像、 css 或脚本)
  4. 重定向到 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


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
)

这几行代码和对正则表达式的基本了解足以开始构建一个可靠的路由系统。

完全来源

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' );

虽然已经回答,和作者的意图是创建一个前端控制器类型的应用程序,但我张贴的问题要求的文字规则。如果有人有同样的问题。

RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([\d]+)$ $1?id=$3 [L]

以上应该工作的网址 picture.php/Some-text-goes-here/51。没有使用 index.php 作为一个重定向应用程序。