Mysqli підключення до БД (PHP5, PHP7)

Mysqli конектор

Що таке Конектор?

В документації MySQL термін коннектор (connector) відноситься до частини програмного забезпечення, що відповідає за підключення до сервера MySQL. MySQL надає безліч конекторів для різних мов програмування, зокрема для PHP.

Для забезпечення взаємодії PHP додатки з сервером баз даних вам необхідно написати PHP код, який виконує підключення до сервера, виконує запити до бази даних і тому подібні операції. Від програмного забезпечення сервера потрібно надати API, який ваш PHP додаток зможе використовувати, а також функціонал, відповідальний за взаємодію вашого застосування з сервером. Програмне забезпечення, що реалізує такий функціонал, зазвичай називають коннектором, так як воно дозволяє вашому додатку підключитися (to connect) до сервера баз даних. У ряді випадків коннектор для своїх потреб може потребувати додаткові бібліотеки.

Які інструменти для роботи з MySQL пропонує PHP API?

API надає на вибір три набори інструментів для підключення до сервера баз даних MySQL:

o     Розширення PHP MySQL

o     Розширення PHP mysqli

o     Об'єкти даних PHP (PDO)

Кожен з них має свої переваги і недоліки. Метою даного огляду є короткий опис ключових особливостей кожного API.

Що таке розширення PHP MySQL?

Це оригінальне розширення дозволяє розробляти PHP додатки, які можуть взаємодіяти з базою даних MySQL. розширення mysql надає процедурний інтерфейс і призначене для використання з MySQL версії 4.1.3 або більш ранніми версіями. Його також можна використовувати і з більш свіжими версіями СУБД, але в цьому випадку багато можливостей сервера, що з'явилися після версії 4.1.3, будуть недоступні програмісту.

Зауваження:

Якщо ви працюєте з сервером MySQL 4.1.3 або пізніших версій, настійно рекомендується використовувати розширення mysqli.

Що таке PHP розширення mysqli?

Розширення mysqli, або як його ще називають поліпшене (improved) MySQL розширення, було розроблено, щоб дати можливість програмістам в повній мірі скористатися функціоналом MySQL сервера версій 4.1.3 і вище. розширення mysqli включається в поставку PHP версій 5 і вище.

mysqli має ряд переваг і удосконалень у порівнянні з mysql, які полягають в наступному:

o     Об'єктно-орієнтований інтерфейс

o     Підтримка підготовлених запитів

o     Підтримка мультізапросов

o     Підтримка транзакцій

o     Поліпшені можливості налагодження

o     Підтримка вбудованого сервера

Зауваження:

При роботі з MySQL версій 4.1.3 і вище настійно рекомендується використовувати саме це розширення.

Нарівні з об'єктно-орієнтованим розширення надає і процедурний інтерфейс.

Що таке PDO?

Об'єкти даних PHP, або PDO, вдають із себе абстракцію коннектора баз даних для PHP додатків. PDO надає API інтерфейс взаємодії з базою даних, що не залежить від конкретної СУБД. Теоретично, при використанні PDO можна поміняти сервер баз даних, наприклад з Firebird на MySQL, і це призведе лише до незначних змін в PHP коді.

В якості інших подібних абстракцій можна привести JDBC для Java додатків і DBI для Perl.

Поряд з перевагами PDO, такими як простота і переносимість API, є його головний недолік: PDO підтримує не всі можливості сервера баз даних, доступні в останніх версіях MySQL. Наприклад, засобами PDO не можна створювати множинні запити, хоча MySQL їх і підтримує.

Процедурний і об'єктно-орієнтований інтерфейс

Розширення mysqli надає подвійний інтерфейс програмісту. Підтримуються як процедурна, так і об'єктно-орієнтована модель програмування.

Приклад # 1 використання процедурного методу

<?php
$mysqli = mysqli_connect("example.com", "user", "password", "database");
$res = mysqli_query($mysqli, "SELECT 'Будь ласка, використовуйте' AS _msg FROM DUAL");
$row = mysqli_fetch_assoc($res);
echo $row['_msg'];

$mysql = mysql_connect("example.com", "user", "password");
mysql_select_db("test");
$res = mysql_query("SELECT 'розширення mysqlш в проектах.' AS _msg FROM DUAL", $mysql);
$row = mysql_fetch_assoc($res);
echo $row['_msg'];
?>

Результат виконання даного прикладу:

Будь ласка, використовуйте розширення mysqlі в проектах.

Об'єктно-орієнтований інтерфейс

На додаток до процедурного, користувачі можуть використовувати об'єктно-орієнтований інтерфейс. Документація заточена саме під об'єктний інтерфейс. Об'єктно-орієнтований інтерфейс пропонує функції згруповані по цілі їх застосування, що полегшує їх пошук і освоєння. Проте, в практичних прикладах до функцій наводиться код для обох методів.

Якихось принципових відмінностей в продуктивності між інтерфейсами немає. Користувачі вільні у виборі інтерфейсу, грунтуючись на особистих уподобаннях.

Приклад # 2 Об'єктно-орієнтований і процедурний інтерфейси

<?php
$mysqli = mysqli_connect("example.com", "user", "password", "database");
if (mysqli_connect_errno($mysqli)) {
    echo "Помилка з'єднання із MySQL:" . mysqli_connect_error();
}

$res = mysqli_query($mysqli, "SELECT 'A world full of ' AS _msg FROM DUAL");
$row = mysqli_fetch_assoc($res);
echo $row['_msg'];

$mysqli = new mysqli("example.com", "user", "password", "database");
if ($mysqli->connect_errno) {
    echo "Помилка з'єднання із MySQL:" . $mysqli->connect_error;
}

$res = $mysqli->query("SELECT 'choices to please everybody.' AS _msg FROM DUAL");
$row = $res->fetch_assoc();
echo $row['_msg'];
?>

Результат виконання даного прикладу:

A world full of choices to please everybody.

Приклади в цьому посібнику будуть написані в об'єктному стилі з огляду на те, що об'єктному підходу віддавалася перевага при створенні документації.

Змішування стилів

Перемикатися між стилями програмування можна як завгодно часто і в будь-який час, проте робити цього не рекомендується, так як це погіршує читабельність коду і ускладнює його підтримку.

Приклад # 3 Поганий стиль програмування

<?php
$mysqli = new mysqli("example.com", "user", "password", "database");
if ($mysqli->connect_errno) {
    echo "Помилка з'єднання із MySQL:" . $mysqli->connect_error;
}

$res = mysqli_query($mysqli, "SELECT 'Цей код працює, але краще так не писати.' AS _msg FROM DUAL");
if (!$res) {
    echo "Неможливо виконати запит: (" . $mysqli->errno . ") " . $mysqli->error;
}

if ($row = $res->fetch_assoc()) {
    echo $row['_msg'];
}
?>

Результат виконання даного прикладу:

Цей код працює, але краще так не писати.

 

З'єднання

Сервер MySQL підтримує різні способи передачі даних. З'єднання можуть використовувати TCP / IP протоколи, сокети Unix доменів або іменовані пайпи Windows.

Ім'я хоста localhost має спеціальне призначення. Воно використовується тільки в сокетах Unix доменів. Неможливо відкрити TCP / IP з'єднання, використовуючи в якості імені хоста localhost. Замість нього потрібно поставити 127.0.0.1.

Приклад # 1 Спеціальне призначення localhost

<?php
$mysqli = new mysqli("localhost", "user", "password", "database");
if ($mysqli->connect_errno) {
    echo "Помилка з'єднання із MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
echo $mysqli->host_info . "\n";

$mysqli = new mysqli("127.0.0.1", "user", "password", "database", 3306);
if ($mysqli->connect_errno) {
    echo "Помилка з'єднання із MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

echo $mysqli->host_info . "\n";
?>

Результат виконання даного прикладу:

Localhost via UNIX socket

127.0.0.1 via TCP/IP

Замовчування для параметрів з'єднань

Залежно від функції, що здійснює підключення, якісь параметри можна не задавати. Якщо параметр не заданий, розширення спробує використовувати значення за замовчуванням для цього параметра, яке задано в конфігураційному файлі PHP.

Приклад # 2 Задання значень за замовчуванням

mysqli.default_host=192.168.2.27

mysqli.default_user=root

mysqli.default_pw=""

mysqli.default_port=3306

mysqli.default_socket=/tmp/mysql.sock

Далі, щоб встановити з'єднання, функція передає параметри в клієнтську бібліотеку, якою користується розширення. Якщо бібліотека виявить порожні або відсутні параметри, вона може підставити замість них свої вбудовані значення за замовчуванням.

Вбудовані замовчання для параметрів з'єднання

Якщо ім'я хоста не задано або передана порожній рядок, клієнтська бібліотека використовує для підключення до Unix сокету хоста localhost. Якщо сокет не заданий або переданий порожній рядок, і при цьому викликане підключення до Unix сокету, бібліотека спробує підключитися до сокету /tmp/mysql.sock.

У Windows системах, якщо в якості імені хоста передається ., бібліотека спробує відкрити з'єднання на основі іменованого пайпа. У цьому випадку ім'я сокета буде сприйнято, як ім'я пайпа. Якщо ім'я сокета не задано, то буде використано значення \\.\pipe\MySQL.

Якщо з'єднання не використовує ні сокет Unix домену, ні іменований пайп Windows, і при цьому не заданий порт для підключення, бібліотека використовує номер порту 3306.

Налаштування з'єднання

Налаштування з'єднання дозволяють, наприклад, поставити якісь команди, які потрібно виконати відразу після підключення, або віддати розпорядження використовувати певний набір символів. Налаштування повинні бути задані до підключення до сервера.

Там, де необхідно створити установки з'єднання, операція з'єднання передачі даних в три етапи: функцією mysqli_init() створюється дескриптор підключення, потім підключення налаштовується за допомогою функції mysqli_options(), і нарешті встановлюється мережеве з'єднання з сервером за допомогою функції mysqli_real_connect().

mysqli::options

Об'єктно-орієнтований стиль

bool mysqli::options ( int $option , mixed $value )

mysqli_options() потрібно викликати після mysqli_init() і перед mysqli_real_connect().

option

Налаштування, яке потрібно встановити. Це може бути одне з наступних значень:

Допустимі налаштування

Ім’я

Опис

MYSQLI_OPT_CONNECT_TIMEOUT

таймаут з'єднання в секундах (підтримується в Windows з TCP / IP, починаючи з PHP 5.3.1)

MYSQLI_OPT_LOCAL_INFILE

включення / виключення LOAD LOCAL INFILE

MYSQLI_INIT_COMMAND

команда, яку потрібно виконати відразу після підключення до сервера MySQL

MYSQLI_READ_DEFAULT_FILE

Читати настройки з файлу замість my.cnf

MYSQLI_READ_DEFAULT_GROUP

Читати настройки з іменованої групи в файлі my.cnf або іншому файлі, заданим настроюванням MYSQL_READ_DEFAULT_FILE.

MYSQLI_SERVER_PUBLIC_KEY

Файл публічного ключа RSA для авторизації на базі SHA-2560.

MYSQLI_OPT_NET_CMD_BUFFER_SIZE

Розмір внутрішнього командного / мережевого буфера. Працює тільки з mysqlnd.

MYSQLI_OPT_NET_READ_BUFFER_SIZE

Максимальний розмір блоку для читання в байтах при читанні командного пакета MySQL. Працює тільки з mysqlnd.

MYSQLI_OPT_INT_AND_FLOAT_NATIVE

Перетворює стовпці типів integer і float до числам PHP, а не рядках. Працює тільки з mysqlnd.

MYSQLI_OPT_SSL_VERIFY_SERVER_CERT

Обов’язково перевірити сертифікат безпеки серверу

 

value

Значення параметру налаштування.

 

mysqli::real_connect

Об'єктно-орієнтований стиль

bool mysqli::real_connect ([ string $host [, string $username [, string $passwd [, string $dbname [, int $port [, string $socket [, int $flags ]]]]]]] )

host

Може бути ім'ям хоста або IP адресою. передача NULL або рядка "localhost" цим параметром означає, що в якості хоста буде використовуватися локальна машина, на якій запущений скрипт. Якщо є така можливість, будуть використовуватися пайпи замість протоколу TCP / IP.

username

Ім'я користувача MySQL.

passwd

Якщо не заданий або дорівнює NULL, MySQL сервер в першу чергу спробує зайти під користувачем який має пароль, а потім буде шукати серед користувачів, у яких немає пароля. Такий підхід дозволяє одному користувачеві призначати різні права (в залежності від того, встановлено пароль чи ні).

dbname

Якщо параметр заданий, його значення буде використовуватися в якості імені бази даних за замовчуванням при виконанні запитів.

port

Порт, до якого буде проводитися підключення.

socket

Задає номер порту для підключення до сервера MySQL.

Зауваження:

Передача параметра socket не буде явно задавати тип з'єднання при підключенні до сервера MySQL. Те, як буде встановлюватися з'єднання з MySQL сервером, визначене параметром host.

flags

За допомогою параметра flags можна задати деякі настройки з'єднання:

Підтримувані значення

Ім’я

Опис

MYSQLI_CLIENT_COMPRESS

Використовувати протокол стиснення

MYSQLI_CLIENT_FOUND_ROWS

Повертати кількість рядків, що підійшли умові вибірки, замість кількості змінених запитом рядків

MYSQLI_CLIENT_IGNORE_SPACE

Допускати пробіли після імен функцій. Робить всі імена функцій зарезервованими словами.

MYSQLI_CLIENT_INTERACTIVE

Допускати interactive_timeout секунд (замість wait_timeout) простою, перш ніж закрити з'єднання

MYSQLI_CLIENT_SSL

Використовувати SSL (шифрування)

MYSQLI_CLIENT_SSL_DONT_

VERIFY_SERVER_CERT

Аналогічно MYSQLI_CLIENT_SSL, але забороняє перевірку SSL сертифікату. Працює тільки з MySQL Native Driver і MySQL 5.6 і вище.

 

Виконання запитів

За виконання запитів відповідають функції mysqli_query(), mysqli_real_query() и mysqli_multi_query(). Найчастіше застосовується функція mysqli_query(), так як вона виконує відразу два завдання: виконує запит і буферизує на клієнті результат цього запиту (якщо він є). виклик mysqli_query() ідентичний послідовному викликом функцій mysqli_real_query() и mysqli_store_result().

Приклад # 1 Підключення до MySQL

<?php
$mysqli = new mysqli("example.com", "user", "password", "database");
if ($mysqli->connect_errno) {
    echo "Помилка з'єднання із MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
    !$mysqli->query("CREATE TABLE test(id INT)") ||
    !$mysqli->query("INSERT INTO test(id) VALUES (1)")) {
    echo "Неможливо створити таблицю: (" . $mysqli->errno . ") " . $mysqli->error;
}
?>

Буферизація результатів запиту

Після виконання запиту його результати можна цілком буферизувати на клієнті, або читати по порядку із сервера. Буферизація на клієнті дозволяє серверу якнайшвидше звільняти зайняті запитом ресурси. Почергове ж читання і подальша обробка результатів клієнтом досить повільний процес. Тому рекомендується використовувати буферизацію результуючих наборів. функція mysqli_query() поєднує в собі операції виконання запиту і буферизації результуючого набору.

PHP додатки можуть вільно оперувати даними всередині буферизованих результатів запитів. Швидка навігація по рядках наборів обумовлена ​​тим, що набори повністю розташовуються в пам'яті клієнта. Слід пам'ятати, що найчастіше обробка результатів на клієнті простіше, ніж засобами сервера.

Приклад # 2 Навігація по рядках буферизує результуючої таблиці

<?php
$mysqli = new mysqli("example.com", "user", "password", "database");
if ($mysqli->connect_errno) {
    echo "Помилка з'єднання із MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

$res = $mysqli->query("SELECT id FROM test ORDER BY id ASC");

echo "Зворотній порядок ... \ n";
for ($row_no = $res->num_rows - 1; $row_no >= 0; $row_no--) {
    $res->data_seek($row_no);
    $row = $res->fetch_assoc();
    echo " id = " . $row['id'] . "\n";
}

echo "Вихідний порядок рядків ... \ n";
$res->data_seek(0);
while ($row = $res->fetch_assoc()) {
    echo " id = " . $row['id'] . "\n";
}
?>

Результат виконання даного прикладу:

Зворотний порядок ... id = 3 id = 2 id = 1 Вихідний порядок рядків ... id = 1 id = 2 id = 3

Небуферизовані результати запитів

Якщо клієнтські ресурси обмежені, і в той же час не потрібно підтримувати низьке навантаження на сервер, можна використовувати не буферизовані результати запитів. Навігація по таких таблицях неможлива.

Приклад # 3 Навігація по рядку не буферизованої результуючої таблиці

<?php
$mysqli->real_query("SELECT id FROM test ORDER BY id ASC");
$res = $mysqli->use_result();

echo "Порядок рядків в результуючому наборі ... \ n";
while ($row = $res->fetch_assoc()) {
    echo " id = " . $row['id\'] . "\n";
}
?>

Приклад № 5 Отримання вихідних типів даних в додатку

<?php
$mysqli = mysqli_init();
$mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 1);
$mysqli->real_connect("example.com", "user", "password", "database");

if ($mysqli->connect_errno) {
    echo "Помилка з'єднання із MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
    !$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))") ||
    !$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')")) {
    echo "Неможливо створити таблицю: (" . $mysqli->errno . ") " . $mysqli->error;
}

$res = $mysqli->query("SELECT id, label FROM test WHERE id = 1");
$row = $res->fetch_assoc();

printf("id = %s (%s)\n", $row['id'], gettype($row['id\']));
printf("label = %s (%s)\n", $row['label'], gettype($row['label']));
?>

Результат виконання даного прикладу:

id = 1 (integer)

label = a (string)

 

Додаткові функції, які можуть знадобитися у роботі

mysqli::$affected_rows

Отримує число рядків, змінених попередньою операцією MySQL. Вхідних параметрів не має

mysqli::close

Закриває раніше відкрите з'єднання з базою даних.

Відкриті непостійні з'єднання MySQL і результуючі набори автоматично видаляються відразу після закінчення роботи PHP скрипта. Отже, закривати з'єднання і очищати результати запитів не обов'язково, але рекомендується, так як це відразу ж звільнить ресурси бази даних і пам'ять, займану результатами вибірки, що може позитивно позначитися на продуктивності.

mysqli::real_escape_string

Екранує спеціальні символи в рядку для використання в SQL виразі

Об'єктно-орієнтований стиль

string mysqli::escape_string ( string $escapestr )

string mysqli::real_escape_string ( string $escapestr )

Ця функція використовується для створення допустимих в SQL рядків, які можна використовувати в SQL виразах. Заданий рядок кодується в екрановану SQL рядок, використовуючи поточний набір символів підключення.

escapestr

Рядок, який потрібно екранувати.

Єкрануються символи NUL (ASCII 0), \n, \r, \, ', ", і Control-Z.

повернені значення

Повертає єкранований рядок.