我正在尝试构建一个动态的关键字搜索功能,以便它将列名作为查询生成的数组以及来自表单发布的关键字传递给它。它对任何关键字和精确短语(每个都使用此处未显示的另一套编程集)都适用,但是需要获取所有关键字的部分却给我带来了一些问题。基本上,我需要知道它何时完成了对第一个关键字的第一次遍历,以便它可以对任何有很多关键字的下一个遍历添加一个AND到WHERE子句中。
我在下面尝试通过使用值的百分比将其切换为AND,但无法完全解决数学问题,因此需要一些帮助。对于此测试,共有9列,只有两个关键字,但是每个关键字都可以变化。
// Fetch the keywords
$keyword = (isset($_POST['s_keyword'])) ? $_POST['s_keyword'] : "";
// Subtract one because ID column is not being used
$len = ((count(array_keys($queryField))-1) * count($keywords));
// Count basic fields to check, subtract one since ID is not being used
$lenbase = (count(array_keys($queryField))-1);
$i = - (count($keywords)); // Subtract number of keywords
foreach ($keywords as $keyword) :
$keyword = str_replace("'", "''", trim($keyword));
foreach (array_keys($queryField) as $column) :
$i++;
if ($column === 'ID') continue;
if (strlen($Where) == 0) $Where .= " WHERE (";
if ($len %$lenbase != 0) $Where .= "(`$column` LIKE '%" . $keyword . "%') AND ";
if ($i != $len) $Where .= "(`$column` LIKE '%" . $keyword . "%') OR ";
if ($i == $len) $Where .= "(`$column` LIKE '%" . $keyword . "%') ";
endforeach;
endforeach;
它正在从表单发布中检索关键字
$keyword = (isset($_POST['s_keyword'])) ? $_POST['s_keyword'] : "";
$keywords = explode(" ", trim($keyword));
在没有 if($ len%$ lenbase!= 0) 等条件的情况下,它可以获取任何关键字但不是全部的关键字(为此添加了一个空格清晰度):
WHERE ((`StorageArea` LIKE '%Paso%')
OR (`Size` LIKE '%Paso%')
OR (`Winery` LIKE '%Paso%')
OR (`Brand` LIKE '%Paso%')
OR (`Appellation` LIKE '%Paso%')
OR (`ReleaseYear` LIKE '%Paso%')
OR (`Varietal` LIKE '%Paso%')
OR (`Status` LIKE '%Paso%')
OR (`CountryName` LIKE '%Paso%')
OR (`StorageArea` LIKE '%Robles%')
OR (`Size` LIKE '%Robles%')
OR (`Winery` LIKE '%Robles%')
OR (`Brand` LIKE '%Robles%')
OR (`Appellation` LIKE '%Robles%')
OR (`ReleaseYear` LIKE '%Robles%')
OR (`Varietal` LIKE '%Robles%')
OR (`Status` LIKE '%Robles%')
OR (`CountryName` LIKE '%Robles%'))
但是我正在寻找:
WHERE ((`StorageArea` LIKE '%Paso%')
OR (`Size` LIKE '%Paso%')
OR (`Winery` LIKE '%Paso%')
OR (`Brand` LIKE '%Paso%')
OR (`Appellation` LIKE '%Paso%')
OR (`ReleaseYear` LIKE '%Paso%')
OR (`Varietal` LIKE '%Paso%')
OR (`Status` LIKE '%Paso%')
OR (`CountryName` LIKE '%Paso%')
AND (`StorageArea` LIKE '%Robles%')
OR (`Size` LIKE '%Robles%')
OR (`Winery` LIKE '%Robles%')
OR (`Brand` LIKE '%Robles%')
OR (`Appellation` LIKE '%Robles%')
OR (`ReleaseYear` LIKE '%Robles%')
OR (`Varietal` LIKE '%Robles%')
OR (`Status` LIKE '%Robles%')
OR (`CountryName` LIKE '%Robles%'))
输入$ queryField是一个数组,它是根据查询动态生成的,然后将其剥离为键,在这种情况下,它看起来像这样:
Array
(
[0] => ID
[1] => StorageArea
[2] => Size
[3] => Winery
[4] => Brand
[5] => Appellation
[6] => ReleaseYear
[7] => Varietal
[8] => Status
[9] => CountryName
)
答案 0 :(得分:2)
$keywords = ['Paso', 'Robles'];
$columns = ['ID', 'StorageArea', 'Size', 'Winery', 'Brand', 'Appellation', 'ReleaseYear', 'Varietal', 'Status', 'CountryName'];
$where = 'WHERE ' . implode(' AND ', array_map(function ($keyword) use ($columns) {
$keyword = str_replace("'", "''", $keyword);
return '(' . implode(' OR ', array_map(function ($column) use ($keyword) {
return "`$column` LIKE '%$keyword%'";
}, array_filter($columns, function ($column) {
return $column !== 'ID';
}))) . ')';
}, $keywords));
基本上:
array_map
在使用array_filter
过滤掉ID
列之后,返回给定关键字的所有子条件的数组,implode
与OR
相连,array_map
在将所有连接的OR
(用关键字包围)之后返回一个数组,所有这些连接的implode
(每个关键字一个),AND
将与[
<column1> LIKE '%<keyword1>%',
<column2> LIKE '%<keyword1>%,
...
]
的那些连接起来,创建最终子句。换句话说,我们来自:
array_map
(内部<column1> LIKE '%<keyword1>%
OR <column2> LIKE '%<keyword1>%
OR ...
的数组结果)join
(内部[
(<column1> LIKE '%<keyword1>% OR <column2> LIKE '%<keyword1>% OR...),
(<column1> LIKE '%<keyword2>% OR <column2> LIKE '%<keyword2>% OR...), ...
]
的字符串结果)array_map
(外部(<column1> LIKE '%<keyword1>% OR <column2> LIKE '%<keyword1>% OR...)
AND (<column1> LIKE '%<keyword2>% OR <column2> LIKE '%<keyword2>% OR...)
AND ...
的数组结果)join
(外部\n
的字符串结果)。 演示:https://3v4l.org/GqEXQ (添加了SELECT COUNT(1)
FROM
(
SELECT
med.Name AS medicine
FROM
Mutations mut
INNER JOIN
Medications med ON med.MemberId = mut.MemberId
WHERE
mut.Mutation IN ('mut1','mut2')
GROUP BY
med.Name
HAVING
COUNT(DISTINCT mut.Mutation) = 2
) Q
个字符以产生更清晰的输出)
答案 1 :(得分:0)
我相信,鉴于有关数据结构的信息有限,您应该在外部foreach关闭之前立即放置您的代码和部分代码。您将需要检查循环是否还没有结束,因为如果有循环,则需要省略和关闭sql语句(我想就是这样)。
foreach($arrayvalue as $array):
foreach($array as $arr):
// where where where
endforeach;
// and or close it here.
if ($i !== $len) {
// apply and
} else {
// apply closing data
}
endforeach;