【发布时间】:2011-02-11 03:32:08
【问题描述】:
我正在使用 PHP 和 Apache 开发一个网站。 我想把我的网址从
www.example.com/book.php?book=title
如果可能的话,当然是这样的:
www.example.com/book/title
注意书名是唯一的,不能重复。
我已经阅读过这方面的内容,但对于像我这样的初学者来说,没有一篇文章足够清晰。 你们知道任何解释这一点的教程吗?
谢谢。
【问题讨论】:
我正在使用 PHP 和 Apache 开发一个网站。 我想把我的网址从
www.example.com/book.php?book=title
如果可能的话,当然是这样的:
www.example.com/book/title
注意书名是唯一的,不能重复。
我已经阅读过这方面的内容,但对于像我这样的初学者来说,没有一篇文章足够清晰。 你们知道任何解释这一点的教程吗?
谢谢。
【问题讨论】:
这是 kohana(以及 99.99% 的 php 框架)的方式
添加一个 .htaccess 文件(如果使用 apache)
# Turn on URL rewriting
RewriteEngine On
RewriteBase /
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php/$0 [PT,L]
这会将所有 url 重定向到 index.php。 index.php 将是某种基于 url 加载脚本的前端控制器
所以在你的例子中:
本地主机/书籍/标题
index.php 将被加载。它将进入 url 并获取要加载的页面(控制器),这实际上会完成所有工作。在这种情况下可能是books.php。 books.php 将从 url 中获取书名,然后搜索数据库或使用该名称执行任何操作。
【讨论】:
我在我的网页中创建了一个静态格式的内部链接,例如“http://www.example.com/casestudy/34”。
我在 .htaccess 文件中写了以下代码:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^casestudy/([^-]+) /casestudy_details.php?id=$1 [R=301,QSA,L]
【讨论】:
您正在寻找的功能称为“url 重写”。
您可以手动完成:您使用正则表达式解释模式,然后网络服务器翻译请求。 对于 Apache,它通常位于 htaccess 文件下,或 httpd.conf 中的 directyl 下。 见官方文档。这里:http://httpd.apache.org/docs/2.0/misc/rewriteguide.html
但设置起来并不“那么”容易,尤其是调试正则表达式。
关于你的问题,试试这样的规则:
RewriteEngine on
RewriteRule ^book/(.*)$ book.php?book=$1 [L]
另一种选择是使用 php 框架:大多数时候,此功能是内置的。 您必须“学习”如何使用该框架。如果您的网站已经完成,这不是最佳选择...
【讨论】:
稍微扩展@Rodolphe 和@Galen 的回复。
如果您对 url 重写的需求有限,使用 Rodolphe 示例中描述的规则硬编码 .htaccess 会很好。
但是,正如 Galen 所建议的那样,您的需求可能是未知的,或者您可能希望稍后扩展它们,而无需触及您的重写规则,一旦您让它们工作。
一种常见的方法是围绕www.host.com/controller/action/parameter 的URL 方案设计您的应用程序。此类 URL 的一个示例可能是 www.host.com/book/view/1,然后可以在内部以多种方式进行处理。
1)
每个控制器都有单独的脚本。然后,您将每个请求重写为 $controller.php?action=$action&param=$param 形式,将不匹配或无效的请求重定向到默认控制器。
# Serve files and directories as per usual,
RewriteCond %{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !-d
# If the request uri doesn't end in .php
# and isn't empty, rewrite the url
RewriteCond %{REQUEST_URI} !.php$
RewriteCond %{REQUEST_URI} !^$
# Try matching against a param request first
RewriteRule (.*?)/(.*?)/(.*?) $1.php?action=$2¶m=$3 [L]
# If it didn't match, try to match an action
RewriteRule (.*?)/(.*?) $1.php?action=$2 [L]
# redirect all other requests to index.php,
# your default controller
RewriteRule .* index.php [L]
2)
您有一个入口点(或前端控制器),您将每个请求重定向到该入口点,该前端控制器负责将请求重定向到相应的控制器。
# Redirect all requests that isn't a file or
# directory to your front controller
RewriteCond %{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !-d
RewriteRule .* index.php [L]
通用后备规则不会将任何参数附加到默认/前端控制器。但是,由于它是内部重定向,因此您可以访问 PHP 中的 REQUEST_URI 来确定您应该做什么。
这些自然不是您唯一的选择。只需我的 2 美分在汤里搅拌一下。
免责声明: 上面所有的重写规则(当然还有其他所有规则)都是直接写在我脑海中的(喝了几杯啤酒之后),还没有在任何地方进行过测试。
【讨论】:
大多数解决方案都依赖于mod_rewrite。例如See here。
【讨论】: