Как преобразовать скрипт с использованием функций mysql_ для использования функций mysqli_?

EDIT: использовать или не использовать mysqli_ выходит за рамки этого вопроса. Рассмотрим использование PDO.


Какие шаги необходимо предпринять, чтобы преобразовать скрипт из использования устаревших функций mysqli_ в mysqli_ ?

Есть ли что-то, что нужно сделать по-другому при использовании mysqli_ вместо mysql ?

Вот базовый сценарий с использованием функций mysql_ :

 <?php //define host, username and password $con = mysql_connect($host,$username,$password); if (!$con) { die('Could not connect: ' . mysql_error()); } $db_name ="db1"; mysql_select_db($dbname, $con); $value1 = mysql_real_escape_string($input_string); $query = 'SELECT * FROM table1 WHERE table1.col1=' . $value1 . ''; $result = mysql_query($query, $con); while($row = mysql_fetch_assoc*$result) { $col1 = $row['col1']; $col2 = $row['col2']; echo $col1 . ' ' . $col2 . '<br />'; } mysql_close($con); ?> 

Примечание. Преобразование из mysql_ в mysqli_ может оказаться не оптимальным. Рассмотрим PDO, если вы готовы преобразовать весь свой код в ООП .

Может возникнуть соблазн попытаться заменить все экземпляры mysql_ на mysqli_ и помолиться. Вы будете близки, но не совсем на высоте.

Подключение к базе данных:

К счастью, mysqli_connect работает достаточно близко к mysql_query что вы можете просто заменить имена своих функций.

mysql_:

 $con = mysql_connect($host, $username, $password); 

mysqli_:

 $con = mysqli_connect($host, $username, $password); 

Выбор базы данных

Теперь, используя большинство других функций в библиотеке mysqli_ , вам необходимо передать mysqli_select_db соединение с базой данных в качестве первого параметра. Для большинства функций mysqli_ требуется объект соединения.

Для этой функции вы можете просто переключить порядок аргументов, переданных функции. Если вы ранее не передавали объект соединения, вы должны добавить его в качестве первого параметра.

mysql_:

 mysql_select_db($dbname, $con); 

mysqli_:

 mysqli_select_db($con, $dbname); 

В качестве бонуса вы также можете передать имя базы данных в качестве четвертого параметра в mysqli_connect – минуя необходимость вызова mysqli_select_db .

 $con = mysqli_connect($host, $username, $password, $dbname); 

Санизировать ввод пользователя

Использование mysqli_real_escape_string очень похоже на mysql_real_escape_string . Вам просто нужно передать объект соединения в качестве первого параметра.

mysql_:

 $value1 = mysql_real_escape_string($input_string); 

mysqli_:

 $value1 = mysqli_real_escape_string($con, $input_string); 

Очень важно: подготовка и запуск запроса

Одной из причин, по mysql_ функции mysql_ были устаревшими для начала, была их неспособность обрабатывать подготовленные операторы. Если вы просто конвертируете свой код в mysqli_ не делая этого важного шага, вы подвержены некоторым из самых слабых мест в mysql_ .

Стоит прочитать эти статьи на подготовленных заявлениях и их преимуществах:

Википедия – Подготовленные заявления

PHP.net – подготовленные отчеты MySQLi

Примечание. При использовании подготовленных операторов лучше явно указывать каждый столбец, который вы пытаетесь запросить, вместо того, чтобы использовать * нотацию для запроса ко всем столбцам. Таким образом, вы можете обеспечить mysqli_stmt_bind_result всех столбцов в своем вызове mysqli_stmt_bind_result .

mysql_:

 $query = 'SELECT * FROM table1 WHERE table1.col1=' . $value1 . ''; $result = mysql_query($query, $con); while($row = mysql_fetch_assoc*$result) { $col1 = $row['col1']; $col2 = $row['col2']; echo $col1 . ' ' . $col2 . '<br />'; } 

mysqli_:

 $query = 'SELECT col1,col2 FROM table1 WHERE table1.col1=?'; if ($stmt = mysqli_prepare($link, $query)) { /* pass parameters to query */ mysqli_stmt_bind_param($stmt, "s", $value1); /* run the query on the database */ mysqli_stmt_execute($stmt); /* assign variable for each column to store results in */ mysqli_stmt_bind_result($stmt, $col1, $col2); /* fetch values */ while (mysqli_stmt_fetch($stmt)) { /* on each fetch, the values for each column in the results are automatically stored in the variables we assigned using "mysqli_stmt_bind_result" */ echo $col1 . ' ' . $col2 . '<br />'; } /* close statement */ mysqli_stmt_close($stmt); } 

Показаны ошибки

Показ ошибок работает несколько иначе с mysqli_ . mysqli_error требует, чтобы объект подключения был первым параметром. Но что, если соединение не получилось? mysqli_ вводит небольшой набор функций, которые не требуют объекта соединения: функции mysqli_connect_* .

mysql_:

 if (!$con) { die('Could not connect: ' . mysql_error()); } if (!$result) { die('SQL Error: ' . mysql_error()); } 

mysqli_:

 /* check connection error*/ if (mysqli_connect_errno()) { die( 'Could not connect: ' . mysqli_connect_error() ); } /* check query error */ if ($stmt = mysqli_prepare($link, $query)) { // ... execute query if (mysqli_stmt_error($stmt)) { echo 'SQL Error: ' . mysqli_stmt_error($stmt); } } 

ПРИМЕР.

Это ваш класс dbc

 <?php class dbc { public $dbserver = 'server'; public $dbusername = 'user'; public $dbpassword = 'pass'; public $dbname = 'db'; function openDb() { try { $db = new PDO('mysql:host=' . $this->dbserver . ';dbname=' . $this->dbname . ';charset=utf8', '' . $this->dbusername . '', '' . $this->dbpassword . ''); } catch (PDOException $e) { die("error, please try again"); } return $db; } function getAllData($qty) { //prepared query to prevent SQL injections $query = "select * from TABLE where qty = ?"; $stmt = $this->openDb()->prepare($query); $stmt->bindValue(1, $qty, PDO::PARAM_INT); $stmt->execute(); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); return $rows; } ?> 

ваша страница PHP:

 <?php require "dbc.php"; $getList = $db->getAllData(25); foreach ($getList as $key=> $row) { echo $row['columnName'] .' key: '. $key; } 

Не конвертируйте mysql_-функции в mysqli_. Период.

Для этого нет никакой причины.

Во-первых, нет причин делать это просто механически, изменяя только имена функций, оставляя алгоритм одинаковым:

Без реализации параметризованных запросов такой ход имеет мало смысла.
Если ваше единственное беспокойство – ошибки «Устаревшие», вы можете просто отключить их

 error_reporting(E_ALL & ~E_DEPRECATED); 

и продолжать счастливо использовать старый mysql_ *
Обратите внимание, что вам понадобится только через 2-3 года, когда PHP 5.5 достигнет общих хостов.
Поэтому нет необходимости торопиться.

Во-вторых, то, что вам действительно нужно, – это устранить все вызовы с открытым кодом API из кода

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

Наконец, единственной реальной причиной переключения с mysql_* на mysqli_* являются параметризованные запросы.

И mysqli совершенно неприменим с ними.

С подготовленными заявлениями PDO – единственный выбор, который у вас есть.

Позвольте мне показать вам, что я имею в виду.
Представьте, что у нас есть массив флажков из HTML-формы для динамического добавления запроса.
С PDO мы можем иметь некоторый относительно нормальный и довольно краткий (но все же бесполезно сложный и загрязненный) код:

 $in = str_repeat('?,', count($_GET['cat']) - 1) . '?'; $sql = "SELECT * FROM table WHERE category IN ($in)"; $stm = $db->prepare($sql); $stm->execute($_GET['cat']); $data = $stm->fetchAll(); - $in = str_repeat('?,', count($_GET['cat']) - 1) . '?'; $sql = "SELECT * FROM table WHERE category IN ($in)"; $stm = $db->prepare($sql); $stm->execute($_GET['cat']); $data = $stm->fetchAll(); 

С mysqli такой тривиальный случай займет у вас часы написания и отладки нескольких страниц чрезвычайно сложного кода.

Просто попробуй и посмотри.

Однако даже PDO требует некоторого неясного и бесполезного кода для создания определенных частей запроса. Таким образом, лучший способ – использовать более интеллектуальную библиотеку, такую ​​как safemysql , которая будет выполнять всю работу внутри, от привязки к извлечению, делая весь ваш код в одну строку :

 $data = $db->getALL("SELECT * FROM table WHERE category IN (?a)", $_GET['cat']);