我正在尝试在数据库中搜索$_POST['search']
中传递的一个或多个关键字,但无法循环浏览这些关键字。
代码已从https://code-boxx.com/php-mysql-search/修改
我的脚本是:
$str = $_POST['search'];
$keywords = preg_split('/[\s]+/', $str);
$totalKeywords = count($keywords);
$query = "";
$i = 0;
while($keywords[i] != null)
{
$query .= " AND name LIKE %".$keywords[i]."%" ;
}
$stmt = $pdo->prepare("SELECT * FROM MYTABLE WHERE MATCH (name) AGAINST (?) ". $query ." ");
$stmt->execute([$_POST['search']]);
$results = $stmt->fetchAll();
理想情况下,搜索应如下所示:
SELECT * FROM MYTABLE WHERE MATCH (name) AGAINST (Keyword1 Keyword2 Keyword3) AND name LIKE '%Keyword1%' AND name LIKE '%Keyword2%' AND name LIKE '%Keyword3%
搜索页面:
<?php
if (isset($_POST['search'])) {
require "2.php";
}
?>
<!DOCTYPE html>
<html>
<body>
<!-- [SEARCH FORM] -->
<form method="post">
<input type="text" name="search" required/>
<input type="submit" value="Search"/>
</form>
<!-- [SEARCH RESULTS] -->
<?php
if (isset($_POST['search'])) {
if (count($results) > 0) {
echo $sql;
foreach ($results as $r) {
printf("<div>%s</div>", $r['name']);
}
} else {
echo "No results found";
}
}
?>
</body>
</html>
感谢任何帮助。
答案 0 :(得分:2)
在使用准备好的语句时,请避免将值直接注入查询语句中。您将失去为他们准备的目的。
因此,首先,您可以将陈述分为两部分。
一个是match against
,两个是where like
部分。
因此,首先构建基本查询:
$sql = "SELECT * FROM MYTABLE WHERE 1=1"; // base query
从那里开始,您可以在构建过程中追加对和的类似条款的匹配项。
然后,根据位创建匹配项:
MATCH (name) AGAINST (Keyword1* Keyword2* Keyword3* IN BOOLEAN MODE) // the ideal query
MATCH (name) AGAINST (? ? ? IN BOOLEAN MODE) // convert to question mark placeholders
要创建它,只需根据输入的数量将问号插入(粘上)空格即可。
$against_placeholder = implode(' ', array_fill(0, $totalKeywords, '?')); // = ? ? ?
并创建where like子句:
(name LIKE ? OR name LIKE ? OR name LIKE ?) // = like keyword1 or like keyword2 or like keyword3
所以在您的代码中:
$like_placeholder = implode(' OR ', array_fill(0, $totalKeywords, 'name LIKE ?'));
因此将它们拼凑在一起:
$against_placeholder = implode(' ', array_fill(0, $totalKeywords, '?'));
$like_placeholder = implode(' OR ', array_fill(0, $totalKeywords, 'name LIKE ?'));
$sql .= " AND MATCH (name) AGAINST ({$against_placeholder}) AND ({$like_placeholder})"; // build the query with placeholders
这将产生一个完整的查询语句,如下所示:
SELECT * FROM MYTABLE WHERE 1=1 AND (MATCH (name) AGAINST (? ? ? IN BOOLEAN MODE)) AND (name LIKE ? OR name LIKE ? OR name LIKE ?)
然后剩下的就是在执行中构建实际的有效负载。剩下的就是这
$sql = "SELECT * FROM MYTABLE WHERE 1=1"; // base query
$against_placeholder = implode(' ', array_fill(0, $totalKeywords, '?'));
$like_placeholder = implode(' OR ', array_fill(0, $totalKeywords, 'slug LIKE ?'));
$sql .= " AND (MATCH (slug) AGAINST ({$against_placeholder} IN BOOLEAN MODE)) OR ({$like_placeholder})"; // build the query with placeholders
// prep input
$against_keywords = array_map(function($value) {
return "{$value}*";
}, $keywords);
$where_keywords = array_map(function($value) {
return "%{$value}%";
}, $keywords);
$keywords = array_merge($keywords, $where_keywords);
$stmt = $pdo->prepare($sql);
$stmt->execute($keywords);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);