У меня есть форма с несколькими входами, которые являются моими фильтрами. Это мой код (не все, только часть, которую я хочу исправить):
$req_resumo = ''; $req_status = ''; $req_usuario = ''; $n_req = 0; $parametros = ""; // Checks which fields are filled and increases the number of filters for future usage if (isset($_POST['usuario']) && $_POST['usuario'] != "") { $req_usuario = $_POST['usuario']; $n_req++; } if (isset($_POST['resumo']) && $_POST['resumo'] != "") { $req_resumo = $_POST['resumo']; $n_req++; } if (isset($_POST['status']) && $_POST['status'] != "") { $req_status = $_POST['status']; $n_req++; } // Then (there is some code between these parts) if ($n_req > 0 && $funcao != 'usuario') $parametros.= " where "; if ($req_usuario != "") { $parametros.= " usuario = '$req_usuario' "; if ($n_req > 1) $parametros.= " and "; } if ($req_resumo != "") { $parametros.= " resumo = '$req_resumo' "; if ($n_req > 1 && ($req_status != "") || ($req_data_inicial != "")) $parametros.= " and "; } if ($req_status != "") { $parametros.= " status = '$req_status' "; } // This will create the query and add the parameters string at the end. $tot = mysqli_query($con, "SELECT * FROM solicitacoes $parametros");
Этот код выглядит уродливым, и даже для меня (begginer), он не чувствует себя хорошо, не похоже на способ кодирования.
Итак, есть ли лучший и простой способ построения этого кода?
$predicates = array(); if ($_POST['usuario'] != "") { $predicates[] = "usuario = '{$_POST["usuario"]}'"; } if ($_POST['resumo'] != "") { $predicates[] = "resumo = '{$_POST["resumo"]}'" } if ($_POST['status'] != "") { $predicates[] = "status = '{$_POST["status"]}'" } if (count($predicates) == 0) { // handle case when nothing specified in POST } else { $tot = mysqli_query($con, "SELECT * FROM solicitacoes WHERE " . implode(" and ", $predicates) ); }
У меня может быть не вся ваша логика, как требуется … но идеи есть. Используйте implode()
для вставки and
между предикатами WHERE
(он будет определять, сколько из них требуется, если они есть). Кроме того, поскольку ваша HTML-форма отправляет POST, вы можете быть уверены, что по крайней мере какое-то значение передается для каждой переменной POST (поэтому isset()
не требуется).
Попробуй. Из моего тестирования локально (без db) выглядел правильно.
$n_req = 0; $_POST['usuario'] = 'test'; $_POST['resumo'] = 'test2'; $_POST['status'] = 'test3'; if (!empty($_POST['usuario'])) { $req_usuario = $_POST['usuario']; $where[] = " usuario = ? "; $params[] = $req_usuario; $n_req++; } if (!empty($_POST['resumo'])) { $req_resumo = $_POST['resumo']; $where[] = " resumo = ? "; $params[] = $req_resumo; $n_req++; } if (!empty($_POST['status'])) { $req_status = $_POST['status']; $where[] = " status = ? "; $params[] = $req_status; $n_req++; } $sql_where = !empty($where) ? ' where ' . implode(' and ', $where) : ''; echo $sql_where; $tot = mysqli_prepare($con, "SELECT * FROM solicitacoes $sql_where"); if(!empty($params)) { //foreach($params as $param) { // mysqli_stmt_bind_param($tot, "s", $param); //echo $param; //} $params = array_merge(array($tot), array(str_repeat('s', count($params))), array_values($params)); print_r($params); call_user_func_array('mysqli_stmt_bind_param', $params); // adapated from https://stackoverflow.com/questions/793471/use-one-bind-param-with-variable-number-of-input-vars and http://www.pontikis.net/blog/dynamically-bind_param-array-mysqli may need to be altered } echo "SELECT * FROM solicitacoes $sql_where"; mysqli_execute($tot);
Если все три значения заполнены, ваш запрос должен быть
SELECT * FROM solicitacoes, где usuario =? и resumo =? и статус =?
?
заполняются значениями драйвером позже в этом процессе. Это предотвращает добавление пользователем (-ами) вредоносного кода для обработки обработки SQL-запросов.
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28Parameterized_Queries.29
Как я могу предотвратить SQL-инъекцию в PHP?
Я также не видел, где был установлен $funcao
.
Вы можете прокомментировать функции mysqli
и разложить эхо-строки, чтобы увидеть, что делает код. Вот как я подтвердил, что запросы строились так, как ожидалось.