Почему PDO лучше избегать запросов и запросов MySQL, чем mysql_real_escape_string?
Мне сказали, что лучше использовать PDO
для ускорения MySQL, а не mysql_real_escape_string
.
Может быть, у меня день смерти мозга (или это может быть тот факт, что я не являюсь воображением естественным программистом, и я все еще очень нахожусь на стадии новичка, когда речь идет о PHP), но, проверив руководство по PHP и прочитав запись в PDO, я все еще не понимаю, что такое PDO и почему это лучше чем при использовании mysql_real_escape_string
. Возможно, это связано с тем, что я еще не справился с сложностями ООП (я предполагаю, что это что-то связано с ООП), но кроме факта, что переменные и значения массива, похоже, Я все еще не уверен, что это на самом деле и как вы его используете (и почему это лучше, чем mysql_real_escape_string
. (Это также может иметь отношение к тому факту, что у меня нет четкого представления о том, что такое классы "есть, поэтому, когда я читаю" класс PDO ", я на самом деле не самый мудрый).
Прочитав статью или две в бит 'Developer Zone' на веб-сайте MySQL, я все еще не понимаю. Поскольку я не могу даже понять, что это на данный момент, я думаю, что, вероятно, использование этого немного вне меня сейчас, но меня все еще интересует расширение моего образования и выяснение того, как я могу улучшить ситуацию.
Может ли кто-нибудь объяснить мне на "простом английском", что такое PDO (или указать мне в сторону чего-то на предмет, написанный на простом английском языке), и как вы собираетесь его использовать?
Ответы
Ответ 1
Как только текущие ответы вникают в детали, а ваш вопрос больше нацелен на общий обзор, я попробую:
Классы PDO нацелены на инкапсуляцию всех функций, необходимых для взаимодействия с базой данных. Они делают это, определяя "методы" (OO-салон для функций) и "свойства" (OO-комната для переменных). Вы использовали бы их как полную замену для всех стандартных функций, которые вы используете сейчас для разговора с базой данных.
Поэтому вместо вызова серии функций mysql_doSomething(), сохраняя свои результаты в ваших собственных переменных, вы будете "создавать экземпляр" объекта из класса PDO ( "класс" = абстрактное определение, "объект" = конкретный, пригодный для использования экземпляр класса) и методы вызова для этого объекта, чтобы сделать то же самое.
В качестве примера, без PDO, вы бы сделали что-то вроде этого:
// Get a db connection
$connection = mysql_connect('someHost/someDB', 'userName', 'password');
// Prepare a query
$query = "SELECT * FROM someTable WHERE something = " . mysql_real_escape_string($comparison) . "'";
// Issue a query
$db_result = mysql_query($query);
// Fetch the results
$results = array();
while ($row = mysql_fetch_array($db_result)) {
$results[] = $row;
}
тогда как это будет эквивалент с использованием PDO:
// Instantiate new PDO object (will create connection on the fly)
$db = new PDO('mysql:dbname=someDB;host=someHost');
// Prepare a query (will escape on the fly)
$statement = $db->prepare('SELECT * FROM someTable WHERE something = :comparison');
// $statement is now a PDOStatement object, with its own methods to use it, e.g.
// execute the query, passing in the parameters to replace
$statement->execute(array(':comparison' => $comparison));
// fetch results as array
$results = $statement->fetchAll();
Итак, с первого взгляда нет большой разницы, кроме синтаксиса. Но версия PDO имеет некоторые преимущества, самая большая из которых - независимость базы данных:
Если вам нужно поговорить с базой PostgreSQL, вы должны изменить только mysql:
на pgsql:
в экземпляре вызова new PDO()
. С помощью старого метода вам придется пройти весь свой код, заменив все функции mysql_doSomething() на их "pg_doSomthing()" (всегда проверяя потенциальные различия в обработке параметров). То же самое было бы для многих других поддерживаемых движков базы данных.
Итак, чтобы вернуться к вашему вопросу, PDO в основном просто дает вам другой способ добиться того же самого, предлагая некоторые ярлыки/улучшения/преимущества. Например, экранирование будет происходить автоматически надлежащим образом, необходимым для используемого вами механизма базы данных. Также подстановка параметров (предотвращает SQL Injections, не показанные в примере) намного проще, что делает ее менее подверженной ошибкам.
Вы должны прочитать некоторые основы ООП, чтобы получить представление о других преимуществах.
Ответ 2
Я не очень хорошо знаком с PDO, но существует различие между "подготовленными операциями" и экранированными строками. Escaping - это удаление запрещенных строк символов из запроса, но подготовленные операторы примерно сообщают базе данных, какой запрос ожидать.
Запрос имеет несколько частей
Подумайте об этом так: когда вы даете запрос в базу данных, вы говорите ему несколько отдельных вещей. Одно может быть, например, "я хочу, чтобы вы сделали выбор". Другой может быть "ограничить его строками WHERE, имя пользователя - следующее значение".
Если вы создаете запрос в виде строки и передаете ее в базу данных, она не знает ни о какой части, пока не получит заполненную строку. Вы можете сделать это:
'SELECT * FROM transactions WHERE username=$username'
Когда он получает эту строку, он должен проанализировать ее и решить, что "это SELECT
с WHERE
".
Приведение деталей в замешательство
Предположим, что злонамеренный пользователь вводит свое имя пользователя как billysmith OR 1=1
. Если вы не будете осторожны, вы можете поместить это в свою строку, в результате чего:
'SELECT * FROM transactions WHERE username=billysmith OR 1=1'
..., который возвратит все транзакции для всех пользователей, потому что 1 всегда равно 1. Упс, вы были взломаны!
Посмотрите, что произошло? База данных не знала, какие части ожидать в вашем запросе, поэтому она просто разбирает строку. Не удивительно, что WHERE
имел OR
, с двумя условиями, которые могли бы его удовлетворить.
Сохранение частей прямо
Если бы он знал , что ожидать, а именно SELECT
, у которого WHERE
было только одно условие, злоумышленник не мог обмануть его.
С подготовленным выражением вы можете дать ему правильное ожидание. Вы можете сообщить базе данных "Я собираюсь отправить вам SELECT
, и она будет ограничена строками WHERE username =
строкой, которую я собираюсь вам дать. Все это - нет других частей для запрос. Готовы ли вы? ОК, здесь идет строка для сравнения с именем пользователя."
С этим ожиданием база данных не будет обманута: она вернет строки, где столбец username
содержит фактическую строку "billysmith OR 1 = 1". Если никто не имеет этого имени пользователя, он ничего не вернет.
Другие преимущества подготовленных операторов
В дополнение к преимуществам безопасности подготовленные заявления имеют несколько преимуществ скорости:
- Их можно повторно использовать с разными параметрами, которые должны быть быстрее, чем создавать новый запрос с нуля, потому что база данных уже знает, в чем вы хотите спросить. Он уже построил "план запроса".
- Некоторые базы данных (Postgres - это один, я думаю) начнут составлять план запроса, как только они получат подготовленный оператор - прежде чем вы действительно отправите параметры для использования с ним. Таким образом, вы можете увидеть ускорение даже по первому запросу.
Для другого объяснения см. Ответ Тео здесь.
Ответ 3
В отличие от mysql_real_escape_string, PDO позволяет вам применять тип данных.
<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>
Обратите внимание, что в приведенном выше примере первый параметр, калории, должен быть целым числом (PDO:: PARAM_INT).
Во-вторых, мне, PDO параметризованные запросы легче читать. Я бы предпочел прочитать:
SELECT name FROM user WHERE id = ? AND admin = ?
чем
SELECT name FROM user WHERE id = mysql_real_escape_string($id) AND admin = mysql_real_escape_string($admin);
В-третьих, вам не обязательно обязательно указывать параметры. PDO заботится об этом. Например, mysql_real_query_string:
SELECT * FROM user WHERE name = 'mysql_real_escape_string($name)' //note quotes around param
против
SELECT * FROM user WHERE name = ?
Наконец, PDO позволяет вам переносить ваше приложение на другой db, не изменяя ваши вызовы данных PHP.
Ответ 4
Представьте, что вы пишете что-то по строкам:
$query = 'SELECT * FROM table WHERE id = ' . mysql_real_escape_string($id);
это не спасет вас от инъекций, потому что $id может быть 1 OR 1=1
, и вы получите все записи из таблицы. youd должен придать $id правильному типу данных (int в этом случае)
pdo имеет еще одно преимущество, и это взаимозаменяемость баз данных.
Ответ 5
В дополнение к предотвращению SQL-инъекции PDO позволяет вам подготовить запрос один раз и выполнить его несколько раз. Если ваш запрос выполняется несколько раз (например, в цикле), этот метод должен быть более эффективным (я говорю "должно быть", потому что похоже, что это не всегда относится к более старым версиям MySQL). Метод prepare/bind также больше соответствует другим языкам, с которыми я работал.
Ответ 6
Почему PDO лучше для ускорения запросов/запросов MySQL, чем mysql_real_escape_string?
Просто потому, что "побега" само по себе не имеет смысла.
Кроме того, имеет значение несравнимый.
Единственная проблема с экранированием заключается в том, что все ошибаются,, считая это своего рода "защитой".
Все говорят: "Я избежал моих переменных" со значением "Я защитил свой запрос".
Хотя экранирование не имеет ничего общего с защитой.
Защита может быть примерно достигнута в случае Я экранировал и процитировал мои данные, но он неприменим везде, например, для идентификаторов (а также PDO).
Итак, ответ:
- PDO при выполнении экранирования привязанных значений применяется не только к экранированию, но и к цитированию - почему это лучше.
- "escaping" не является синонимом "защиты". "ускользание + цитирование" примерно есть.
- но для некоторых частей запроса оба метода неприменимы.