Каков процедурный 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 ответа

Чтобы защитить ваш запрос от инъекционной атаки, у вас есть два варианта. Первый - очень простой и безопасный, как подготовленное заявление.

  1. В ролях $pid как целое число

    $query = "SELECT post_title, post_content FROM wp_posts WHERE ID = " . (int)$pid;
    

    Безопасно и сделано.

  2. Как написать подготовленное утверждение с привязкой результата... (Я не использую процедурный синтаксис 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;
Другие вопросы по тегам