Каков процедурный mysqli способ подготовки операторов SQL?
В моем коде есть запрос SQL, который я хочу преобразовать в подготовленный оператор, чтобы остановить уязвимости, такие как инъекции SQL. Вот что я хочу преобразовать:
<?php
$query = "SELECT * from `wp_posts` WHERE ID=$pid ";
$result = mysqli_query($link, $query);
//$id=$row['Gallery_Id'];
while($row = mysqli_fetch_array($result)){
?>
<h2 align="center"> <?php echo $row['post_title']; ?> </h2><br>
<div class="paracenter">
<p id="cont"><?php echo $row['post_content']; ?></p>
<hr color="black" width="10%">
</div>
<?php } ?>
Это то, что я пытался, но это не работает.
$query = "SELECT * from `wp_posts` WHERE ID=? ";
$stmt = mysqli_prepare($link, $query);
if($stmt){
mysqli_stmt_bind_param($stmt, "i", $pid);
mysqli_stmt_bind_result($stmt, $dbpid);
mysqli_stmt_execute($stmt);
mysqli_stmt_fetch($stmt);
}
$result = mysqli_query($link, $query);
//$id=$row['Gallery_Id'];
while($row = mysqli_stmt_fetch($result)){
?>
<h2 align="center"> <?php echo $row['post_title']; ?> </h2><br>
<div class="paracenter">
<p id="cont"><?php echo $row['post_content']; ?></p>
<hr color="black" width="10%">
</div>
<?php } ?>
Почти все примеры онлайн не используют процедурный метод, который я использую. Как я могу исправить это?
2 ответа
Чтобы защитить ваш запрос от инъекционной атаки, у вас есть два варианта. Первый - очень простой и безопасный, как подготовленное заявление.
В ролях
$pid
как целое число$query = "SELECT post_title, post_content FROM wp_posts WHERE ID = " . (int)$pid;
Безопасно и сделано.
Как написать подготовленное утверждение с привязкой результата... (Я не использую процедурный синтаксис mysqli)
if (!$stmt = $link->prepare("SELECT post_title, post_content FROM wp_posts WHERE ID = ?")) { echo "Syntax Error @ Prepare"; // $link->error; <-- never show actual error details to public } elseif (!$stmt->bind_param("i", $pid) || !$stmt->execute() || !$stmt->bind_result($title, $content)) { echo "Syntax Error @ ParamBind | Execute | ResultBind"; // $stmt->error; <-- never show actual error details to public } else { while ($stmt->fetch()) { echo "<div>"; echo "<h2 align=\"cente\">$title</h2><br>"; echo "<div class=\"paracenter\">"; echo "<p id=\"cont\">$content</p>"; echo "<hr color=\"black\" width=\"10%\">"; echo "</div> "; } }
Некоторые дополнительные заметки.
- Если вы не собираетесь использовать привязку результатов, вы должны использовать
mysqli_fetch_assoc()
вместоmysqli_fetch_array()
,mysqli_fetch_array()
создаст раздутый результирующий набор как индексированных, так и ассоциативных ключевых элементов (вдвое больше, чем вам действительно нужно). - Когда вы используете
bind_result()
нужно заменить*
в предложении SELECT со столбцами, которые будут извлечены. - Мой первый
elseif()
Выражение содержит три отдельных вызова и проверки на$stmt
, Как только любой из этих вызовов возвращает ложный / ошибочный ответ, условные выражения в коротких замыканиях и остальные вызовы в выражении никогда не выполняются. - Если вы принимаете мой объектно-ориентированный стиль mysqli, убедитесь, что выровняли синтаксис соединения с базой данных как объектно-ориентированный.
Явно выберите столбцы, которые вы позже получите, вместо использования*
в вашем предложении SELECT.
Параметр привязывается по ссылке, поэтому$pid
должен быть объявлен, а затем использовать - в отличие от прямой записи целого числа2
непосредственно в вызове привязки.
При привязке результата предлагайте переменные, соответствующие столбцам в предложении SELECT.
Код: (Демо-версия PHPize.online)
$pid = 2;
$sql = <<<SQL
SELECT post_title, post_content
FROM wp_posts
WHERE ID=?
SQL;
$stmt = mysqli_prepare($mysqli, $sql);
mysqli_stmt_bind_param($stmt, "i", $pid);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $title, $content);
if (mysqli_stmt_fetch($stmt)) {
?>
<h2 align="center"><?php echo $title; ?></h2><br>
<div class="paracenter">
<p id="cont"><?php echo $content; ?></p>
<hr color="black" width="10%">
</div>
<?php
}
Тем не менее, вы пишете код внутри приложения Wordpress, а Wordpress имеет свои собственные вспомогательные методы, обеспечивающие функциональность подготовленных операторов (хотя они не имеют процедурного синтаксиса, но они привлекательны и аккуратны).
$row = $wpdb->get_results($wpdb->prepare($sql, [$pid]));
if ($row) {
?>
<h2 align="center"><?php echo $title; ?></h2><br>
<div class="paracenter">
<p id="cont"><?php echo $content; ?></p>
<hr color="black" width="10%">
</div>
<?php
}
И, наконец, вероятно, наиболее целесообразно использовать специальную функцию Wordpress.get_post()
.
https://developer.wordpress.org/reference/functions/get_post/
$post = get_post($pid);
// $post->post_title;
// $post->post_content;