Я должен создать запрос на основе определенных условий. Существует ли лучший способ сделать его, чем способ, которым я сделал ниже? Это хорошо работает, но я вижу, что он выходит из-под контроля справедливо быстро, если было больше условий, так как я проверяю, соблюдали ли какие-либо предыдущие условия каждый раз, когда я проверяю новый.
$sql = "SELECT DISTINCT fkRespondentID FROM tblRespondentDayTime";
if (!empty($day) || !empty($time) || !empty($sportID)) {
$sql .= " WHERE";
if (!empty($day)) {
$sql .= " fldDay='$day'";
}
if (!empty($time)) {
if (!empty($day)) {
$sql .= " AND";
}
$sql .= " fldTime='$time'";
}
if (!empty($sportID)) {
if (!empty($day) || !empty($time)) {
$sql .= " AND";
}
$sql .= " fkRespondentID IN (SELECT fkRespondentID FROM tblRespondentSport WHERE fkSportID='$sportID')";
}
}
Я бы использовал старый «WHERE 1 = 1»
трюк; добавьте это как первое условие, а затем вы можете принять условие «И» для каждого следующего оператора.
$sql = "SELECT DISTINCT fkRespondentID FROM tblRespondentDayTime WHERE 1=1";
if (!empty($day))
$sql .= "AND fldDay='$day'";
if (!empty($time)) {
$sql .= "AND fldTime='$time'";
if (!empty($sportID))
$sql .= "AND fkRespondentID IN (SELECT fkRespondentID FROM tblRespondentSport WHERE fkSportID='$sportID')";
Создайте список / массив условий, в котором каждое условие является необязательным (т.е. если условие действительно, поместите его в список).
Если этот список> 0, добавьте «где», а затем добавьте список, соединенный «и».
Вместо того, чтобы выполнять такие проверки, как if (! Empty ($ day) ||! Empty ($ time))
, вы можете создать $ whereClause
переменную и проверьте ее следующим образом:
$sql = "SELECT DISTINCT fkRespondentID
FROM tblRespondentDayTime";
$whereClause = '';
// fldDay
if (!empty($day)) {
$whereClause .= " fldDay='$day'";
}
// fldTime
if (!empty($time)) {
if (!empty($whereClause)) {
$whereClause .= ' AND ';
}
$whereClause .= " fldTime='$time'";
}
// fkRespondentID
if (!empty($sportID)) {
if (!empty($whereClause)) {
$whereClause .= ' AND ';
}
$whereClause .= " fkRespondentID IN (SELECT fkRespondentID
FROM tblRespondentSport
WHERE fkSportID='$sportID')";
}
if (!empty($whereClause)) {
$whereClause = ' WHERE '.$whereClause;
}
$sql .= $whereClause;
Это также сработает, если вам нужно, скажем, изменить некоторые на ИЛИ
(1 = 1 трюк в этом случае не сработает и даже может оказаться довольно опасным ).
вы можете попробовать поместить свои переменные в массив и иметь логическое значение, которое сообщает, нужно ли вам добавить «И» перед следующей фразой. Это сократит ваши управляющие операторы до foreach и вложенного if.
Вот мое решение:
$sql = "SELECT * FROM table";
$conditions = array(
'fldDay' => $day,
'fldTime' => $time,
);
if (count(array_filter($conditions))) {
$sql .= ' WHERE ';
$sql .= implode(' AND ', array_map(function($field, $value) {
return $field . '=\'' . pg_escape_string($value) . '\'';
}, array_keys($conditions), $conditions));
}
Обратите внимание, что из-за закрытий это не будет работать ниже PHP 5.3. Если вы используете старый PHP, сделайте закрытие отдельной функцией или замените его на foreach
.
К сожалению, создание динамического SQL - утомительное занятие, и даже если вы можете изменить несколько вещей в своей логике (которая на самом деле выглядит относительно чистой), это все равно будет некрасиво.
К счастью, Объектно-реляционное отображение существует. Я не слишком знаком с PHP, но Perl имеет несколько модулей CPAN, таких как SQL :: Abstract, которые позволят вам создавать довольно сложные операторы SQL с использованием базовых структур данных.
Если вы используете хранимые процедуры, вы можете сделать что-то вроде этого:
CREATE PROCEDURE `FindRespondents` (
IN `_day` varchar(255),
...
)
BEGIN
SELECT DISTINCT fkRespondentID
FROM tblRespondentDayTime
WHERE (_day Is Null OR fldDay = _day)
AND ...
END;
|
Передача null
для _day
означает, что любой fldDay
допустим. Любое другое значение для _day
, и оно должно быть сопоставлено. Я предположил, что fldDay
- это текст, но, конечно, вы можете ввести здесь все правильно.
Я знаю, что некоторые люди не поклонники хранимых процедур, но может быть удобно инкапсулировать логику запросов таким образом.