Что это
MySQLi(MySQL Improved/улучшенный Mysql) является улучшенной версией старого драйвера PHP MySQL.
Почему нужно
Разработка php_mysql остановилась на поддержке функционала MySQL 4.1.3. Это расширение не поддерживает транзакции, объектный интерфейс, подвержено уязвимостям при подстановке значений в запрос.
О чем пост
О подготовленных выражениях, транзакциях, двойном синтаксисе и о том, как упростить пользование библиотекой до уровня DbSimple.
Позволяют установить выражение единожды, а затем многократно исполнить его с разными параметрами. Помимо этого они позволяют отделить переменные от запроса.
Существует три причины использовать подготовленные выражения:
Это безопаснее, чем оперирование данными внутри строки
Скорость выполнения выше
Так быстрее писать код
Сравнительная таблица MySQLi, PDO и php_mysql
Как это выглядит по-умолчанию
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
/* проверяем соединение */
if (mysqli_connect_errno()) {
printf("Ошибка соединения: %s\n", mysqli_connect_error());
exit();
}
$city = "Ярославль";
/* создаем подготовленное выражение */
if ($stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=?")) {
/* связываем параметр */
$stmt->bind_param("s", $city);
/* исполняем запрос */
$stmt->execute();
/* прикрепляем результаты*/
$stmt->bind_result($district);
/* выбираем значение */
$stmt->fetch();
printf("%s находится в %s\n", $city, $district);
$stmt->close();
}
/* закрываем соединение */
$mysqli->close();
?>
Результатом будет: "Ярославль находится в России".
И это здорово, но в один-момент меня посетила мысль, что я не хочу писать так каждый раз, чтобы получить результат выполнения запроса. Так и родился класс SimpleMysqli(с php_mysql и pdo кстати такая же штука- много кода, мало дела).
Класс SimpleMysqli
SVN:
http://simple-mysqli-class.googlecode.com/svn/trunk/
Подключение к проекту:
require_once("class.simpleDB.php");
require_once("class.simpleMysqli.php");
или настройте ваш autoload на 'class.'.$className.'.php'
Я достаточно много времени работал с DbSimple, поэтому избрал очень похожий синтаксис.
Пример подключения к БД:
$settings=array(
'server' => 'localhost',
'username' => 'root',
'password' => '',
'db' => 'my_database',
'port' => 3306,
'charset' => 'utf8',
);
$db=new simpleMysqli($settings);
Пример выборки:
$query=$db->select('SELECT * FROM test WHERE id >?',1001);
// Ответ:
Array
(
[0] => Array
(
[id] => 1002
[val] => another
)
[1] => Array
(
[id] => 1003
[val] => habra
)
)
В классе реализованы следующие типы запросов:
Выборка строки: selectRow()
Выборка ячейки: selectCell()
Выборка столбца: selectCol()
Выполнение обновлений: select()
Вставка данных: insert()
Удаление: delete()
Замена: replace()
Запросы select-типов возвращают результат выборки в том или ином виде, все остальные возвращают bool(true/false). В случае необходимости получения количества обновленных столбцов или количества выбранных строк можно обратиться к публичному члену $queryInfo, который содержит массив следующего вида:
array(
'affected_rows' => ,
'insert_id' => ,
'num_rows' => ,
'field_count' => ,
'sqlstate' => ,
);
Подготовка выражений на клиенте
Довольно большой неприятностью могут встать выборки типа:
SELECT * FROM `test` WHERE id IN(1,2,3,4,...,101)
По-умолчанию вам предлагается либо всегда точно знать количество заменителей и писать запрос вида:
SELECT * FROM `test` WHERE id IN(?,?,?,?,...,?)
либо работать со строкой, что не безопасно.
Для таких случаев я ввел дополнительный плэйсхолдер %s, который корректно решает непрятности с массивами в рамках идеологии подготовленных выражений. Важно: класс в таком случае не работает со строкой. Он добавляет члены массива как аргументы и заменяет %s на нужное количество "?". Безопасность не страдает.
Пример:
$arr=array(1,2,3);
$query=$db->select('SELECT * FROM test WHERE id IN(%s)',$arr);
// эквиваленто:
$query=$db->select('SELECT * FROM test WHERE id IN(?,?,?)',1,2,3);
Транзакции
Класс также реализует транзакции:
$this->db_localhost->transactionStart();
$this->db_localhost->simpleQuery('DELETE from table');
$this->db_localhost->simpleQuery('DELETE from another_table');
$this->db_localhost->transactionCommit();
Хотя класс и включает функционал работы с транзакциями это то, что я хочу в первую очередь переписать, так как функционал пока скудненький.
PS
Пожалуйста, не пользуйтесь php_mysql.