我正在寻找解决列出书名的"漂亮链接"或"永久链接"的问题,例如:
http://www.example.com/title/The-Catcher-in-the-Rye/
当我处理具有简单单词或空格的常规书名时,没有问题,因为我可以简单地用破折号-替换空格,并通过做反向。
但是,当我的书名中带有撇号'或冒号:或两者均是本示例时,就会出现问题:
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
我的链接显示了未转义的标题,这些漂亮的链接是通过用短划线代替空格并省略撇号和冒号而创建的,如下所示:
Why Can't I Be You: A Novel
所以,解决我的问题。我希望能够列出格式(未转义)的所有书名,并使用带连字符的"永久链接" /"漂亮链接",并将正确的标题返回给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解决此问题,而不必在数据库中添加诸如slug或permalink的额外表,并且我不想使用撇号在网址中,例如%27为单引号。这是一个大型数据库,可以在电子表格中完成数据输入,导出到CSV并上传到SQL数据库。没有单个条目的前端来允许诸如slug或等效项之类的事情。
希望我的解释清楚。
您的数据不应在标题中以反斜杠存储。 因此,在列出数据之前无需取消转义数据。
为什么我不能在SQL数据库中转义单引号?
在数据库中存储文本时使用转义数据,以便能够正确存储一些特殊字符(如单引号)。 用于转义特殊字符的反斜杠未写入数据库中,因此,当您要从数据库读取数据时,没有任何转义或不转义的内容。
您在存储的数据中看到反斜杠的事实表明您在某处对它进行了太多次转义。 SQL查询可能类似于INSERT ... Why Can\\\t I Be You ...。
首先,在数据库中存储转义字符串的想法看起来很奇怪。 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 |
+-----+-----------------------------+----------------------------+
您应该按此列为表建立索引,并在viewbook.php脚本内的SQL查询中使用它代替book_title,如下所示:
SELECT * FROM books WHERE book_title_url='$booktitle'
其中$booktitle包含通过$_GET['booktitle']接收的书名,并正确转义以防止SQL注入。
因此,您漂亮的URL看起来像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之类的东西。
同样,这是通常实现漂亮URL的常用方法。希望它也对您有用。
对于现有记录,您可以通过以下方式填充book_title_url列:
UPDATE books SET book_title_url=REPLACE(REPLACE(REPLACE(book_title,"","-"),":","-"),"'","-");
我想避免这种情况,但是,考虑一下您的解决方案,再加上@shomeax可以为我做这件事。感谢您的输入和填充新book_title_url列的解决方案
根据STD 66,冒号和撇号在路径段中均有效:
segment = *pchar
pchar = unreserved / pct-encoded / sub-delims /":" /"@"
sub-delims ="!" /"$" /"&" /"'" /"(" /")"
/"*" /"+" /"," /";" /"="
因此,在这种情况下,您可以在未编码的URI中使用它们:
title="Why Can't I Be You: A Novel">Why Can't I Be You: A Novel
感谢您的参考阅读,但是,我承认我的决定更多地是基于"理想"的解决方案,而不是实际的解决方案,尽管它可以按照std66进行工作,但从美学上来讲并不是令人满意的(我知道,设计胜过功能,但是那我的OCD)。
不要忘了通过url进行索引,否则它将工作缓慢,除非您要进行SQL注入,否则请转义来自请求的变量:)
如果您可以选择将整数id嵌入到漂亮的url中,则可以解决所有这些问题,例如:
http://www.whaaa.at/title/1/whatever-fancy-%34name%34-you-like
我将很有可能将其与@Mikhails解决方案结合使用。我想避免这种情况,但实际上并没有" Perfect Pretty Permalinks"之类的东西,我想这更多是" OCD"问题,而不是设计决定。