Apostrophes和Colons in Pretty Links

时间:2013-03-13 16:10:17

标签: php mysql apache .htaccess mod-rewrite

我希望解决一个问题,处理列出书名的“漂亮链接”或“永久链接”,例如:

http://www.example.com/title/The-Catcher-in-the-Rye/

当我处理普通的书籍标题,例如简单的单词或空格时,没有问题,因为我可以简单地用短划线-替换空格并处理在数据库中查找书名。做反向str_replace

但是,如果我的书籍标题中包含撇号'或冒号:,或者两者都有,则会出现问题:

Why Can't I Be You: A Novel

在我的sql数据库中,所有单引号都被转义,因此数据库中的条目如下:

+-----+-------------------------------+
| BID | book_title                    |
+-----+-------------------------------+
|   1 | Why Can\'t I Be You: A Novel  |
+-----+-------------------------------+

当我列出所有书名时,我再次浏览字符串,因此它只列为:Why Can't I Be You: A Novel

我的<a>链接显示未转义的标题,通过用短划线替换空格并省略撇号和冒号来创建漂亮的链接,如下所示:

<a href="http://www.example.com/title/why-cant-i-be-you-a-novel" title="Why Can't I Be You: A Novel">Why Can't I Be You: A Novel</a>

所以,解决我的问题。我希望能够列出格式化(未转义)书籍的所有标题,并使用带有连字符的“永久链接”/“漂亮链接”,并将正确的标题返回给GET方法。

在我的.htaccess条目中,我有以下RewriteRule

RewriteRule ^title/(.*[^/])/?$ viewbook.php?booktitle=$1 [NC,L]

这样做是在title/之后的“漂亮”链接部分,并通过GET将其发送到viewbook.php。例如,对于“麦田里的守望者”一书,下面是通过GET发送的:The-Catcher-in-the-Rye

没问题,因为在php中解决这个问题很简单:

$booktitle = $_GET['booktitle'];
$goodBookTitle = str_replace('-', ' ', $booktitle);

// or we can do it all at once

$booktitle = str_replace('-', ' ', $_GET['booktitle']);

// Send $booktitle to SQL query and find the book

当没有找到撇号时,这种方法很好,但是,如果标题有撇号或冒号,则此方法无效,因为在数据库中找不到它。我也不想使用WHERE book_title LIKE '%$booktitle%',因为viewbook.php必须完全匹配。

我正在寻找一个优雅或简单的解决方案,这将使我能够通过RewriteRule解决这个问题,而不必为数据库添加额外的表格slugpermalink,并且我不想在网址中有撇号,例如%27的单引号。这是一个大型数据库,在该数据库中,数据输入在电子表格中完成,导出为CSV并上载到SQL数据库中。单个条目没有前端允许slug或等同的内容。

我希望我的解释清楚。

3 个答案:

答案 0 :(得分:2)

首先,将转义字符串存储在数据库中的想法看起来很奇怪。 MySQL能够存储任意字符串,甚至可以安全地存储二进制序列。

现在关于从真实标题映射到漂亮的URL并返回。将标题转换为URL友好字符串然后返回的想法并不是解决问题的常用方法,因为很难使这种转换成为可逆的。解决此问题的常用方法是在数据库中使用单独的列,其中包含修改为URL友好的书名。此列中的值也应该是唯一的。该表可能如下所示:

+-----+-----------------------------+----------------------------+
| BID | book_title                  | book_title_url             |
+-----+-----------------------------+----------------------------+
|   1 | Why Can't I Be You: A Novel | why-can-t-i-be-you-a-novel |
+-----+-----------------------------+----------------------------+

您应该按照此列对表进行索引,并在book_title脚本中的SQL查询中使用它而不是viewbook.php,如下所示:

SELECT * FROM books WHERE book_title_url='$booktitle'

其中$booktitle包含通过$_GET['booktitle']收到的图书标题并正确转义以阻止SQL注入。

所以你漂亮的网址看起来像http://www.example.com/title/why-can-t-i-be-you-a-novel,他们会被Apache重写为http://www.example.com/viewbook.php?booktitle=why-can-t-i-be-you-a-novel

同样,这通常是如何实现漂亮网址的常见方式。希望它也适合你。

对于现有记录,您可以通过以下内容填充book_title_url列:

UPDATE books SET book_title_url=REPLACE(REPLACE(REPLACE(book_title, " ", "-"), ":", "-"), "'", "-");

答案 1 :(得分:1)

不要忘记按url索引,否则它会缓慢运行,除非你想要SQL注入,否则请转义来自请求的变量:)

如果您可以选择在漂亮的网址中嵌入整数ID,那么所有这些问题都可以克服: http://www.whaaa.at/title/1/whatever-fancy-%34name%34-you-like 然后按该ID

查找

无论如何,书名不是主键,因为可能有几本同名的书。

答案 2 :(得分:1)

根据STD 66,冒号和撇号在路径段中都有效:

segment    = *pchar

pchar      = unreserved / pct-encoded / sub-delims / ":" / "@"

sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
           / "*" / "+" / "," / ";" / "="

因此,在这种情况下,您可以在未编码的URI中使用它们:

<a href="http://www.example.com/title/why-can't-i-be-you:-a-novel"
   title="Why Can't I Be You: A Novel">Why Can't I Be You: A Novel</a>

维基百科就是这样做的:例如: http://en.wikipedia.org/wiki/Breakin'_2:_Electric_Boogaloo(唉,StackOverflow在创建超链接时对这些字符进行编码)。

真正无法使用的字符必须以某种方式编码(标准化方法是使用百分比编码,但如果您不能接受,则可以执行特定于应用程序的操作某些原因),或者省略(例如通过查看辅助列,如@MikhailVladimirov's answer中所述)。