Правильный синтаксис подготовленных операторов - PullRequest
0 голосов
/ 24 февраля 2012

Я считаю необходимым работать в области, в которой у меня очень мало знаний. Мне нужно обезопасить базу данных веб-сайта, которая использует около 20 вызовов MySQL SELECT для предоставления информации посетителям сайта.Все вызовы имеют вид:

$leadstory = "-1";
if (isset($_GET['leadstory'])) {
  $leadstory = $_GET['leadstory'];
}

$query_News = "SELECT * FROM news WHERE lead_story = $leadstory";
$News = mysql_query($query_News, $HDAdave) or die(mysql_error());
$row_News = mysql_fetch_assoc($News);
$totalRows_News = mysql_num_rows($News);

В предыдущем посте я спросил, уязвимы ли эти операторы SELECT для атак вставки SQL.Ответ был да, как вы все, наверное, знаете.Я немного прочитал и понял, что мне нужно использовать mysqli и что-то вроде следующего:

$statement = $db_connection->prepare("SELECT * FROM news WHERE lead_story = ?;';");
$statement->bind_param("s", $leadstory);
$statement->execute();
$row_News = $statement->fetchAll();

У меня есть несколько вопросов.

  1. Нужно ли мнеЛиния типа " or die " в случае сбоя соединения?

  2. Как назначить $ totalRows_News ?

  3. Мне также нужно " очистить " переменную $leadstory с помощью mysql_real_escape_string?

Ответы [ 2 ]

1 голос
/ 24 февраля 2012
  1. Не использовать or die при выводе HTML.Вы получите недействительный HTML.Часто ошибки обнаруживаются на низком уровне, но могут обрабатываться только на более высоком уровне.Правильная обработка ошибок включает передачу ошибки до тех пор, пока она не будет обработана надлежащим образом.Вы можете использовать возвращаемые значения для хранения ошибок (если могут быть различные типы ошибок и типов ошибок, не связанных с ошибками) или использовать исключения .
  2. Вы можете получить количество строк результата, используяmysqli_result->num_rows или PDOStatement->rowCount.Обратите внимание, что последнее доступно не для всех баз данных, поддерживаемых PDO, но для MySQL.Однако оба требуют буферизованных запросов, что является менее производительным, поскольку запрос должен завершиться до продолжения программы (т. Е. execute является синхронным по отношению к запросу), а весь набор результатов должен быть сохранен в памяти.Метод, показанный Филом, будет работать с другими базами данных, хотя он несет те же затраты производительности, что и буферизованные запросы.Альтернативный небуферизованный запрос (execute является асинхронным по отношению к запросу) заключается в работе со строками по мере их появления, игнорируя общее количество строк до конца.PDOStatement поддерживает Traversable, что означает, что вы можете зациклить его с помощью цикла foreach, поэтому вам не нужно знать общее количество строк для зацикливания.

    ...
    $query->execute(array(':after' => $date));
    foreach ($query as $row) {
        ...
    }
    

    Это делает обработку результатов в других модулях особенно приятной, поскольку им не нужно знать, что они повторяют.Вы даже можете получить результаты, возвращенные в качестве экземпляров данного класса.

    $query->execute(...);
    /* assign properties after calling constructor, so default property
       values set in constructor don't overwrite the values from the DB */
    $query->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'Article');
    
    # elsewhere, $articles has been set to the value of $query
    foreach ($articles as $article) {
        # $article is an Article; do with it what you will.
        ...
    }
    

    Единственный недостаток использования PDOStatement напрямую состоит в том, что результаты запроса обычно имеют однократное использование;если вы не используете курсор, вы можете зациклить их только один раз.

  3. Этот вопрос задавался (вероятно, много раз) раньше: Когда в подготовленных выражениях необходимо указывать цитатыpdo в PHP?

Вы можете думать о готовых операторах как об аналогах функций.С помощью функции вы берете блок кода, параметризуете его часть и упаковываете его.Функцию можно вызывать несколько раз, но ее нужно определить только один раз.То же самое относится и к подготовленным заявлениям.Поскольку значения хранятся отдельно от кода, внедрение невозможно в параметрах подготовленного оператора (внедрение является результатом путаницы данных с кодом ).

Как и в случае с функциями, вы можетепроизвольно заменять части утверждения параметром.Вы должны уважать синтаксис, с одной стороны.Другое ограничение - только определенные вещи могут быть параметризованы.Как функции, так и параметры обычно позволяют только параметризовать значения, хотя в некоторых языках значение считается довольно широким.В SQL то, что считается значением, довольно узко.Идентификаторы (имена для баз данных, таблиц, столбцов, хранимых процедур и т. Д.) Не являются значениями.Списки значений (например, правильный аргумент оператора IN) сами по себе не являются значениями.

Расширение на одну из точек в 1. немного, в хорошо спроектированном проекте код разделен на разныемодули основаны именно на том, какие функции он реализует.Это известно как « разделение интересов » и приводит к таким вещам, как MVC и многоуровневая архитектура.« принцип единоличной ответственности связан (это можно считать подпринципом). Применяя их к данному случаю, вы должны иметь отдельный слой доступа к данным , который отвечает за базу данныхСуществует несколько шаблонов , которые вы можете применять для реализации этого, но существенным аспектом является не что иное, как DAL должен получить доступ к базе данных или быть затронутым изменением способа сохранения данных. DAL может обрабатывать некоторые ошибки самостоятельно(частично или полностью), но это не должно касаться взаимодействия с пользователем или отображения данных.

1 голос
/ 24 февраля 2012

Использование PDO сделает вашу жизнь намного проще

$pdo = new PDO(...);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $pdo->prepare('SELECT * FROM news WHERE lead_story = ?');
$stmt->bindParam(1, $leadStory);
$stmt->execute();

$allRows_News = $stmt->fetchAll();
$totalRows_News = count($allRows_News);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...