我正在使用此功能生成SEO友好的标题,但我认为它可以改进,任何人都想尝试?它做了一些事情:清除常见的重音字母,检查“禁止”数组,并选择性地检查正在使用的标题数据库。
/**
* Recursive function that generates a unique "this-is-the-title123" string for use in URL.
* Checks optionally against $table and $field and the array $forbidden to make sure it's unique.
* Usage: the resulting string should be saved in the db with the object.
*/
function seo_titleinurl_generate($title, $forbidden = FALSE, $table = FALSE, $field = FALSE)
{
## 1. parse $title
$title = clean($title, "oneline"); // remove tags and such
$title = ereg_replace(" ", "-", $title); // replace spaces by "-"
$title = ereg_replace("á", "a", $title); // replace special chars
$title = ereg_replace("í", "i", $title); // replace special chars
$title = ereg_replace("ó", "o", $title); // replace special chars
$title = ereg_replace("ú", "u", $title); // replace special chars
$title = ereg_replace("ñ", "n", $title); // replace special chars
$title = ereg_replace("Ñ", "n", $title); // replace special chars
$title = strtolower(trim($title)); // lowercase
$title = preg_replace("/([^a-zA-Z0-9_-])/",'',$title); // only keep standard latin letters and numbers, hyphens and dashes
## 2. check against db (optional)
if ($table AND $field)
{
$sql = "SELECT * FROM $table WHERE $field = '" . addslashes($title) . "'";
$res = mysql_debug_query($sql);
if (mysql_num_rows($res) > 0)
{
// already taken. So recursively adjust $title and try again.
$title = append_increasing_number($title);
$title = seo_titleinurl_generate($title, $forbidden, $table, $field);
}
}
## 3. check against $forbidden array
if ($forbidden)
{
while (list ($key, $val) = each($forbidden))
{
// $val is the forbidden string
if ($title == $val)
{
$title = append_increasing_number($title);
$title = seo_titleinurl_generate($title, $forbidden, $table, $field);
}
}
}
return $title;
}
/**
* Function that appends an increasing number to a string, for example "peter" becomes "peter1" and "peter129" becomes "peter130".
* (To improve, this function could be made recursive to deal with numbers over 99999.)
*/
function append_increasing_number($title)
{
##. 1. Find number at end of string.
$last1 = substr($title, strlen($title)-1, 1);
$last2 = substr($title, strlen($title)-2, 2);
$last3 = substr($title, strlen($title)-3, 3);
$last4 = substr($title, strlen($title)-4, 4);
$last5 = substr($title, strlen($title)-5, 5); // up to 5 numbers (ie. 99999)
if (is_numeric($last5))
{
$last5++; // +1
$title = substr($title, 0, strlen($title)-5) . $last5;
} elseif (is_numeric($last4))
{
$last4++; // +1
$title = substr($title, 0, strlen($title)-4) . $last4;
} elseif (is_numeric($last3))
{
$last3++; // +1
$title = substr($title, 0, strlen($title)-3) . $last3;
} elseif (is_numeric($last2))
{
$last2++; // +1
$title = substr($title, 0, strlen($title)-2) . $last2;
} elseif (is_numeric($last1))
{
$last1++; // +1
$title = substr($title, 0, strlen($title)-1) . $last1;
} else
{
$title = $title . "1"; // append '1'
}
return $title;
}
答案 0 :(得分:4)
似乎存在竞争条件,因为您正在执行SELECT以查看之前是否已使用过标题,如果没有则返回它(可能是调用代码然后将其插入到DB中)。如果另一个进程执行相同的操作,但它插入SELECT和INSERT之间怎么办?您的插入将失败。你可能应该为URL添加一些保证唯一的令牌(可能是比SEO友好名称高一级的路径中的“目录”,类似于StackOverflow的做法),以避免SEO友好的URL需要的问题是独一无二的。
我还要重写append_increasing_number()
函数以使其更具可读性......让它以编程方式确定最终有多少数字并且正常工作,而不是一个巨大的if / else来解决它。代码将更清晰,更简单,甚至可能更快。
答案 1 :(得分:4)
上面的str_replace建议非常好。此外,您可以用一行替换最后一个函数:
function append_increasing_number($title) {
return preg_replace('@([0-9]+)$@e', '\1+1', $title);
}
您可以做得更好并完全删除循环查询,并执行类似
的操作"SELECT MAX($field) + 1 FROM $table WHERE $field LIKE '" . mysql_escape_string(preg_replace('@[0-9]+$@', '', $title)) . "%'";
在这样的循环中运行SELECT只是丑陋。
答案 2 :(得分:3)
看起来其他人已经达到了大部分重点(特别是关于递增后缀和递归/循环执行SQL查询),但我仍然看到了一些可以做出的重大改进。
首先,不要试图想出你自己的变音符号到ASCII的替代品;你永远不会抓住它们,而且存在更好的工具。特别是,我将注意力转向iconv
的“翻译”功能。您可以将UTF-8(或用于标题的任何编码)转换为普通的旧7位ASCII,如下所示:
$title = strtolower(strip(clean($title)));
$title = iconv('UTF-8', 'ASCII//TRANSLIT', $title);
$title = str_replace("'", "", $title);
$title = preg_replace(array("/\W+/", "/^\W+|\W+$/"), array("-", ""), $title);
请注意,这也修复了原始代码中的错误,其中在trim()
之前调用了空格到破折号的替换,并用单个破折号替换了所有非字母/数字/破坏程序的运行。例如," Héllo, world's peoples!"
变为"hello-worlds-peoples"
。这将取代整个第1部分。
其次,可以重写$forbidden
循环以提高效率并消除递归:
if ($forbidden)
{
while (in_array($title, $forbidden))
{
$title = append_increasing_number($title);
}
}
这取代了第3节。
答案 3 :(得分:2)
你可能会失去:
$title = ereg_replace(" ", "-", $title);
用更快的str_replace()
:
$title = str_replace(" ", "-", $title);
来自str_replace()的PHP手册页:
如果你不需要花哨的替换 规则(如正则表达式),你 应始终使用此功能 而不是
ereg_replace()
或preg_replace()
。
编辑:
我增强了你的append_increasing_number($title)
功能,它完全相同,只是对结尾的位数没有限制(而且它更漂亮:):
function append_increasing_number($title)
{
$counter = strlen($title);
while(is_numeric(substr($title, $counter - 1, 1))) {
$counter--;
}
$numberPart = (int) substr($title,$counter,strlen($title) - 1);
$incrementedNumberPart = $numberPart + 1;
return str_replace($numberPart, $incrementedNumberPart, $title);
}
答案 4 :(得分:2)
按照karim79的回答,第一部分可以更易读,更容易维护:
替换
$title = ereg_replace(" ", "-", $title); // replace spaces by "-"
$title = ereg_replace("á", "a", $title); // replace special chars
$title = ereg_replace("í", "i", $title); // replace special chars
与
$replacements = array(
' ' => '-',
'á' => 'a',
'í' => 'i'
);
$title = str_replace(array_keys($replacements, array_values($replacements), $title);
使用append_increasing_number()的最后一部分看起来很糟糕。您可以删除整个功能,只需执行类似
的操作while ($i < 99999){
//check for existance of $title . $i; if doesn't exist - insert!
}
答案 5 :(得分:1)
你也可以使用带有str_replace()的数组,这样就可以了
$replace = array(' ', 'á');
$with = array('-', 'a');
数组中的位置必须对应。
那应该刮几行,还有几个毫秒。
你还要考虑所有的标点符号,经常会有不同的引号和!等等进入网址。我会在\ W(不是单词)上做一个preg_replace
preg_replace('/\w/', '', $title);
这应该对你有所帮助。
菲尔