C Man 建议的(拆分搜索短语并搜索每个单词)或全文搜索。
对于“分词”的方法,我建议:
- 使用正则表达式进行拆分,例如
preg_match_all('#[a-zA-Z0-9]+#', $text, $words);
你不需要
搜索“$”之类的符号,是吗?
- 编写一个可以为您生成
where 子句的函数。
生成where 子句的函数可能如下所示:
function generateFilter(array $fields, array $words) {
// prepare $word for putting into SQL statement
foreach ( $words as &$word ) {
// ensure that wildcard characters are used as regular characters
$word = str_replace('%', '\\%', $word);
$word = str_replace('_', '\\_', $word);
// prevent SQL injections
$word = mysql_real_escape_string($word);
}
unset($word);
// generate filter
$filter = array();
foreach ( $words as $word ) {
$wordFilter = array();
foreach ( $fields as $field ) {
$wordFilter[] = "{$field} like '%$word%'";
}
$filter[] = implode(' or ', $wordFilter);
}
$filter = '(' . implode(') and (', $filter) . ')';
return $filter;
}
$filter = generateFilter(
array('name', 'surname', 'address'),
array('john', 'doe')
);
echo $filter;
结果:
(name like '%john%' or surname like '%john%' or address like '%john%') and
(name like '%doe%' or surname like '%doe%' or address like '%doe%')
如果你使用准备好的语句(强烈建议),这个函数会有点复杂,因为生成的字符串会有变量的占位符,而 $words 会被放入一些必须绑定到的变量数组中准备好的语句。
“分词”方法适用于小字符串和少量数据。如果您有大量数据和/或大字符串,请考虑使用全文搜索。它不需要拆分搜索短语,尽管它有一些限制 - 它需要对用于搜索的列进行全文索引(IIRC,您可以在多个列上创建索引,然后同时在所有索引列上使用全文搜索,即,您不必单独搜索每一列),它具有最短的关键字长度,并且可能会给出非严格的结果,例如,有时 5 个关键字中可能只有 3 个出现在结果中。但是,它给出了每个结果的相关性——更接近搜索词的结果将具有更高的相关性。这对于按相关性对结果进行排序很有用。
虽然创建索引对您来说似乎是一项“额外工作”,但它可以让 DBMS 比没有索引更快地执行搜索。