Я думаю, что это довольно простой вопрос. Это мой лучший выбор или есть "правильный" способ сделать это?
<?php
$correctOrder = array("name", "address", "phone", "starttime", "endtime",
"status", "details");
$sql->sql1 = "SELECT * FROM 'pickups' WHERE";
if (isset($_GET["name"])){
$sql->sql2 = "'name' LIKE '%" . $_GET['name'] . "%'";
}
if (isset($_GET["address"])){
if (!isset($_GET['name'])){
$q = "'address' LIKE '%" . $_GET['address'] . "%'";
} else {
$q = "AND 'address' LIKE '%" . $_GET['address'] . "%'";
}
$sql->sql3 = $q;
}
...
...
echo implode(" ", (array) $sql);
?>
Итак, прямо сейчас:
?name=Jari%20Martikainen&address=some%20random%20street
а также
?name=Jari%20Martikainen&address=some%20random%20street&blah=har
а также
?address=some%20random%20street&blah=har&name=Jari%20Martikainen
все возвращают тот же результат, который желателен, но он просто не кажется очень эффективным способом делать что-то.
Создайте массив ($ands
) из предложений AND, но без "AND".
$ands = array();
if (...)
$ands[] = "name LIKE ...";
if (...)
$ands[] = "address LIKE ...";
...
Затем постройте запрос:
$query = "SELECT ... WHERE " . implode(' AND ', $ands);
Я считаю, эта модель должна быть простой, чистой, и избегаю кладжи как 1=1
или удаления дополнительного AND
.
Этот код использует массив для определения того, какие параметры ему интересны, и создает массив предложений where.
Причина, по которой я использую "name" => "name"
в этом массиве ($correctOrder
), заключается в том, что он позволяет $correctOrder
имя параметра и имя столбца. Здесь вы должны добавить любые параметры.
Также этот код использует переменные связывания, не уверен, какой вкус базы данных имеет доступ к вашему использованию, но вы можете передать массив $data
для execute
чтобы связать их.
$correctOrder = array("name" => "name", "address" => "address");
$_GET = [ 'name' => 'name1', 'address' => 'add'];
$where = [];
$data = [];
foreach ( $_GET as $paramName => $param ) {
if ( isset($correctOrder[$paramName]) ) {
$where[] = "'{$correctOrder[$paramName]}' like ? ";
$data[] = '%'.$param.'%';
}
}
$sql = "SELECT * FROM 'pickups'";
if ( count($where) > 0 ){
$sql .= " WHERE ".implode( " and ", $where);
}
echo $sql.PHP_EOL;
print_r($data);
Функция count($where) > 0
добавит только предложение where
, если есть что добавить, и implode добавляет соответствующие and
бит в качестве клей.
Что с тестовыми данными дает...
SELECT * FROM 'pickups' WHERE 'name' like ? and 'address' like ?
Array
(
[0] => %name1%
[1] => %add%
)
Это действительно работает только со строками, но вы можете добавить специальный код для других полей данных и добавить предложение в массив $where
прежде чем попасть в финальную часть, которая строит инструкцию.
Здесь немного больше капитального ремонта, чем вы просили.
Сначала начните предложение WHERE с 1 = 1, затем выполните цикл через свой массив поисковых терминов и расширьте предложение where, если какой-либо из них включен в массив $ _GET.
Во-вторых, я бы использовал объект PDO для подключения к вашей базе данных, а затем BIND значения $ _GET. Это поможет защитить вас от SQL-инъекций/взломов.
Ниже я просматриваю поисковые запросы, сохраняя их в массив с именем $ sqlParams, если в массиве $ _GET есть что-то. Затем я просматриваю $ sqlParams и привязываю значения.
// connect to database via PDO
try {
$db = new PDO($dsn, $username, $password, $options);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$correctOrder = array("name", "address", "phone", "starttime", "endtime",
"status", "details");
$sql = "SELECT * FROM 'pickups' WHERE 1=1 ";
// check the $_GET array, build SQL, remember values in $sqlParams
$sqlParams = [];
foreach ($correctOrder as $key) {
if (isset($_GET[$key])) {
$sql .= "and '$key' LIKE :$key ";
$sqlParams[":$key"] = "%{$_GET[$key]}%";
}
}
// bind values from $sqlParams into SQL statement
$stmt = $db->prepare($sql);
foreach ($sqlParams as $key => &$value) {
$stmt->bindParam($key, $value);
}
// execute SQL statement, catching exception
try {
$stmt->execute();
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
// cycle through results and do stuff
while ($row = $stmt->fetch()) {
print_r($row);
}
correctOrder
что происходит? Это не выглядит наиболее эффективным способом выполнения действий - лучшеcorrectOrder