【发布时间】:2019-06-10 19:58:45
【问题描述】:
我正在为一个学校项目构建一个搜索引擎,旨在让用户浏览一个庞大的学校数据库,我已经将它设置为在一个页面上,用户可以勾选某些复选框,并且在点击提交后,用户将返回与勾选内容相对应的学校列表。
允许用户根据多个参数在全国范围内搜索学校:
- 学校类型(高中、初中、贸易学校、大学等...)
- 学校状况(私立或公立)
- 城市
- 状态
- 等
对于我的问题,我将只关注与学校类型相关的部分,因为稍后我可以将逻辑与其他功能类似的表单元素一起应用。
对于学校类型以及许多其他表单元素,我决定使用复选框,例如,如果用户希望搜索返回初中和高中,他只需勾选两者“初中”和“高中”复选框。
因此,这意味着在我的搜索中使用OR 语句,例如,我会使用这样的 SQL 查询:
SELECT schools.schoolId, schools.schoolName, villages.villageName FROM schools, villages
WHERE schools.villageId = villages.villageId
这里是我要设置的条件,即查询只返回与中学、高中和贸易学校有关的信息:
AND (schools.schoolType = "MiddleSchool" OR schools.schoolType = "HighSchool" OR schools.schoolType = "TradeSchool")
我遇到问题的是这个语句的构造。
事实上,因为学校类型会随着数据库的发展而变化,所以我不能硬编码我的查询结构,我也不希望这样做。
我使用 PHP 根据表单结果生成查询。
为了生成所有可用学校类型的列表,我使用 DISTINCT 查询从数据库 (MySQL) 中读取了所有现有学校类型。我用它来构建所有可用学校类型的列表,我用它来生成搜索表单。
因此,我必须使用类似的方法将表单结果与数据库进行比较,这意味着,在我的结果页面上,要查看哪些复选框已被勾选,我需要查看当前可能存在哪些复选框表单已发送,所以我再次从数据库中读取所有可用类型:(一些代码被截断,这只是我使用的查询,我知道它有效,但这只是为了上下文)
try
{
$pdo = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$req_sql_type_school = "SELECT DISTINCT schoolType AS types FROM schools";
$res_type_schools = $pdo->query($req_sql_type_school);
$res_type_schools->setFetchMode(PDO::FETCH_ASSOC);
} catch (PDOException $e)
{
die("Could not connect to the database $dbname :" . $e->getMessage());
}
之后,我遍历查询结果以创建学校类型的数组:(我知道这也可以,但同样,它只是为了上下文)
$arrayTypes = array();
while ($row = $res_type_schools->fetch())
{
$arrayTypes[]=$row['types'];
}
那么,这就是我挣扎的地方。正是在这一点上,我必须在上面提到的查询的开头创建“AND...”语句,即:
SELECT schools.schoolId, schools.schoolName, villages.villageName FROM schools, villages
WHERE schools.villageId = villages.villageId
为了查看用户是否勾选了某些内容,我遍历数组以检查相应的复选框是否被勾选。为此,这是我编写的代码。注意:basictext() 只是将字符串格式化为我用于复选框值的格式,这是只有小写字母的字符串,没有空格和重音符号):
foreach($arrayTypes as $arr)
{
if(isSet($_GET[basictext($arr)]))
{
echo "[x] Type ".$arr." <br/>";
}
else
{
echo "[ ] Type ".$arr." <br/>";
}
}
这使我可以检查用户在搜索表单上检查了哪些类型。
但是,我不知道如何将其翻译成我想要的 AND 语句,就是这个:
AND (schools.schoolType = "MiddleSchool" OR schools.schoolType = "HighSchool" OR schools.schoolType = "TradeSchool")
我曾想过将每种类型放在括号内并用OR 分隔每种类型,并且仅在确实检查了类型时才在括号内写入。
结果如下:
AND ((schools.schoolType = 'MiddleSchool') OR () OR () OR (schools.schoolType = 'HighSchool') OR () OR () OR ())
不用说,它很丑,而且也不起作用,所以我把它装了。问题是我不知道可以有多少“检查类型”,因此构建正确的查询有点困难。
我在写这篇文章时想到的一个解决方案是将每个“有效”类型放在一个数组中,然后使用那个数组,然后我会知道它的长度。然后我将能够创建预期的 AND 语句,因为我将拥有一定数量的选中复选框,并且它还允许我完全忽略未选中的值。你觉得这样行吗?
【问题讨论】:
-
您可能会发现使用
field IN (1,2,3)比使用field = 1 OR field = 2 OR field = 3更容易。 -
WHERE schools.schoolType IN ("MiddleSchool", "HighSchool", "TradeSchool")