1

我正在寻求解决处理列出书籍标题的“漂亮链接”或“永久链接”的问题,例如:

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

当我处理具有简单单词或空格的常规书名时,没有问题,因为我可以简单地用破折号替换空格并-通过执行 reverse 来处理在数据库中查找书名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必须完全匹配。

我正在寻找一个优雅或简单的解决方案,这将使我能够通过 a 解决这个问题,RewriteRule而不必为 say slugor向数据库添加额外的表permalink,并且我不想在 url 中使用撇号,例如 %27 用于单引用。这是一个大型数据库,数据输入在电子表格中完成,导出为 CSV 并上传到 SQL 数据库。单个条目没有前端以允许诸如slug或等效之类的事情。

我希望我的解释清楚。

4

3 回答 3

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'

其中包含通过接收并正确转义以防止 SQL 注入的$booktitle书名。$_GET['booktitle']

所以你漂亮的 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, " ", "-"), ":", "-"), "'", "-");
于 2013-03-16T19:53:55.887 回答
1

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

如果您可以选择在漂亮的 url 中嵌入整数 id,那么所有这些问题都可以克服,就像这样: http: //www.whaaa.at/title/1/whatever-fancy-%34name%34-you-like 然后通过该 id 查找

无论如何,书名不是主键,因为可以有几本书具有相同的标题。

于 2013-03-16T20:05:18.607 回答
1

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

段 = *pchar

pchar = unreserved / pct-encoded / 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>

这就是 Wikipedia 的做法:例如http://en.wikipedia.org/wiki/Breakin'_2:_Electric_Boogaloo(可惜 StackOverflow 在创建超链接时正在对这些字符进行编码)。

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

于 2013-03-16T20:18:08.730 回答