PHP и базы данных MySQL
http://belarusweb.net
Основы создания сайтов

PHP и базы данных MySQL

Пару слов о MySQL

При создании и поддержке динамических веб-сайтов практически невозможно обойтись без использования баз данных. Они повсеместно используются как для упорядоченного и структурированного хранения на сервере необходимой для работы сайта информации, так и для формирования динамически генерируемых по запросам пользователей страниц. Например, в базах данных хранится информация о зарегистрированных пользователях, каталоги товаров, справочная информация или различного вида статистические данные. Однако простым наличием баз данных на сайте дело не ограничивается, поскольку данные нужно не только хранить, но и добавлять, удалять, редактировать, сортировать, делать выборку в соответствии с различными условиями и многое другое. Все это реализуется специальными программами, которые называются системы управления базами данных (СУБД). Более того, СУБД также создают и удаляют непосредственно сами базы данных.

СУБД довольно много, но PHP в большинстве случаев используется в связке с СУБД MySQL, разработку и поддержку которой осуществляет корпорация Oracle, а сам продукт распространяется как под GNU General Public License (свободно распространяемое ПО), так и под собственной коммерческой лицензией.

MySQL, как и большинство СУБД, для построения запросов к базам данных использует общий формальный язык структурированных запросов, называемый SQL (от англ. Structured Query Language). Конечно, каждый из производителей несколько изменяет SQL под свои нужды, поэтому правильнее говорить о диалектах языка запросов SQL. Однако в любом случае после MySQL освоение работы с СУБД других производителей уже не составит большого труда.

Скачать справочное руководство по MySQL на английском языке можно на официальном сайте, совершив переход по ссылке здесь. На первом этапе будет полезным ознакомиться с переводом руководства версии 5.0.6-beta, которое доступно для загрузки на http://mysqlru.com/manual.html. Также с рускоязычным переводом версии 5.0.3-alpha можно ознакомиться на сайте http://phpclub.ru/mysql/doc/.

Расширение MySQLi для работы с MySQL

Одним из расширений ядра PHP для работы с функционалом MySQL версии 4.1 и выше является расширение MySQLi. Для создания подключения к серверу MySQL в расширении MySQLi предусмотрен специальный конструктор mysqli::__construct, который как раз и возвращает объект, представляющий подключение к серверу MySQL. Подробнее о конструкторе и других возможностях расширения MySQLi смотрите в разделе официального справочника Расширения для работы с базами данных -> Расширения для работы с базами данных отдельных производителей -> MySQL -> MySQLi -> mysqli.

Установка соединения с сервером MySQL и отправка запросов

Прежде чем получить возможность редактирования баз данных, необходимо выполнить подключение к серверу баз данных MySQL и войти под учетной записью пользователя, обладающего соответствующими привилегиями. Поскольку MySQL входит в состав сборки Xampp, первоначальный доступ к ней после установки сборки будет осуществляться исходя из стартовых настроек, которые подразумевают наличие учетной записи суперпользователя 'root', обладающего неограниченными привилегиями. При этом первоначальный пароль для доступа к данной учетной записи отсутствует. Запустите приложение phpMyAdmin и убедитесь в этом, после чего внимательно и не спеша изучите примеры ниже, выполнив показанные в них скрипты на локальном сервере.

<?php
//Оформим аргументы, которые необходимо передать конструктору 
//mysqli::__construct, в виде переменных

//Указываем имя хоста, с которого разрешен доступ пользователю
//По умолчанию доступ разрешен с "localhost" (запустите phpMyAdmin и посмотрите)
$servername = "localhost";
//Имя суперпользователя уже присутствует (запустите phpMyAdmin и посмотрите) 
$username = "root"; 
//Пароль пока не требуется
$password = "";

//Создаем объект соединения с MySQL	
$conn = new mysqli ($servername, $username, $password);

//Если произойдет ошибка соединения, то выведем строку с описанием последней ошибки
//подключения, использовав свойство объекта mysqli->connect_error и прервем скрипт
if ($conn->connect_error){   
   //Функция die() выводит сообщение и прекращает выполнение текущего скрипта
   echo "Ошибка соединения с сервером MySQL: ".$conn->connect_error."<br>";
	//Функция die() выводит сообщение и прекращает выполнение текущего скрипта	
	die("Соединение установлено не было.");
} 

//Установим кодировку данных для данного соединения с MySQL, чтобы не было 
//проблем с отображением русских символов.
$conn->set_charset("utf8"); 

//Теперь, когда мы подключились как суперпользователь, можем действовать
//Присвоим переменной строку запроса к серверу MySQL, использовав язык SQL
//Создадим нового пользователя 'administrator'@'localhost' с паролем '12345'
$sql_1 = "CREATE USER 'administrator'@'localhost' IDENTIFIED BY '12345'"; 

//Выполняем запрос и если он прошел успешно, сообщаем об успехе
if ($conn->query($sql_1) === true){
	echo "Пользователь успешно создан.<br>";     
} else {
	//Иначе прекращаем выполнение скрипта и выводим строку с описанием ошибки
	echo "Ошибка создания учетной записи: ".$conn->error.".";   
	//Т.к. соединение нам пока не нужно, закрываем его
	$conn->close();
	//Функция die() прекращает дальнейшее выполнение текущего скрипта	
	die();
}

//Наш пользователь пока не имеет никаких привилегий
//Наделяем пользователя 'administrator' всеми глобальными привилегиями 
//с возможностью изменять привилегии других пользователей
$sql_2 = "GRANT ALL ON *.* TO 'administrator'@'localhost' WITH GRANT OPTION";  

//Выполняем запрос и если он прошел успешно, сообщаем об успехе
if ($conn->query($sql_2) === true){
	echo "Привилегии установлены.<br>";     
} else{
	//Иначе прекращаем выполнение скрипта и выводим строку с описанием ошибки
	echo "Ошибка создания учетной записи: ".$conn->error.".";   
	//Т.к. соединение нам пока не нужно, закрываем его
	$conn->close();
	//Функция die() прекращает дальнейшее выполнение текущего скрипта	
	die();
}

//Т.к. соединение нам пока не нужно, закрываем его
$conn->close();   
?>

Пример 2.1.8.1 Создание учетной записи администратора

Используем созданую нами учетную запись администратора для создания учебной базы belarusweb_users (см. пример 2.1.8.2).

<?php
//Оформим аргументы, которые необходимо передать конструктору 
//mysqli::__construct, в виде переменных

//Имя хоста задаем как "localhost", хотя можем входить с любого компьютера
$servername = "localhost";
//Входим под именем администратора  
$username = "administrator"; 
//Не забываем про пароль
$password = "12345";

//Создаем объект соединения с MySQL	
$conn = new mysqli ($servername, $username, $password);

//Если произойдет ошибка соединения, то выведем строку с описанием последней ошибки
//подключения, использовав свойство объекта mysqli->connect_error и прервем скрипт
if ($conn->connect_error){   
   //Функция die() выводит сообщение и прекращает выполнение текущего скрипта
   echo "Ошибка соединения с сервером MySQL: ".$conn->connect_error."<br>";
	//Функция die() выводит сообщение и прекращает выполнение текущего скрипта	
	die("Соединение установлено не было.");
} 

//Установим кодировку данных для данного соединения с MySQL, чтобы не было 
//проблем с отображением русских символов.
$conn->set_charset("utf8");

//Cоздаем основную учебную базу данных (имя в кавычки брать не нужно)
//Не забываем задать кодировку символов, используемую в ней
$sql_1 = "create database belarusweb_users CHARACTER SET utf8"; 

//Выполняем запрос и если он прошел успешно, сообщаем об успехе
if ($conn->query($sql_1) === true){
	echo "База данных belarusweb_users создана.<br>";     
} else {
	//Иначе прекращаем выполнение скрипта и выводим строку с описанием ошибки
	echo "Ошибка создания базы данных: ".$conn->error.".";   
	//Т.к. соединение нам пока не нужно, закрываем его
	$conn->close();
	//Функция die() прекращает дальнейшее выполнение текущего скрипта	
	die();
}

//Т.к. соединение нам пока не нужно, закрываем его
$conn->close();   
?>

Пример 2.1.8.2. Создание базы данных

Создадим в базе данных таблицу our_users (см. пример 2.1.8.3). В ней мы будем хранить данные о пользователях.

<?php
//Оформим аргументы, которые необходимо передать конструктору 
//mysqli::__construct, в виде переменных

//Имя хоста задаем как "localhost", хотя можем входить с любого компьютера
$servername = "localhost";
//Входим под именем администратора  
$username = "administrator"; 
//Не забываем про пароль
$password = "12345";
//Указываем базу данных, к которой будем  подключаться
$db_name = "belarusweb_users";

//Создаем объект соединения с MySQL	
$conn = new mysqli ($servername, $username, $password, $db_name);

//Если произойдет ошибка соединения, то выведем строку с описанием последней ошибки
//подключения, использовав свойство объекта mysqli->connect_error и прервем скрипт
if ($conn->connect_error){   
   //Функция die() выводит сообщение и прекращает выполнение текущего скрипта
   echo "Ошибка соединения с сервером MySQL: ".$conn->connect_error."<br>";
	//Функция die() выводит сообщение и прекращает выполнение текущего скрипта	
	die("Соединение установлено не было.");
}

//Установим кодировку данных для данного соединения с MySQL, чтобы не было 
//проблем с отображением русских символов.
$conn->set_charset("utf8");

//Cоздаем таблицу our_users (имя в кавычки брать не нужно)
//В скобках перечисляем имена столбцов, а также через пробел их характеристики
$sql = "create table our_users(".
			"ID INT(5) UNSIGNED PRIMARY KEY AUTO_INCREMENT,".
			"first_name VARCHAR(25) NOT NULL,".
			"last_name VARCHAR(25) NOT NULL,".
			"age INT(2) NOT NULL,".
			"sex VARCHAR(8) NOT NULL,".
			"reg_mail VARCHAR(40) NOT NULL,".
			"reg_date TIMESTAMP NOT NULL".
			") CHARACTER SET utf8";  

//Выполняем запрос и если он прошел успешно, сообщаем об успехе
if ($conn->query($sql) === true){
	echo "Таблица успешно создана.<br>";     
} else {
	//Прекращаем выполнение скрипта и выводим строку с описанием ошибки
	echo "Ошибка создания таблицы: ".$conn->error.".";   
	//Т.к. соединение нам пока не нужно, закрываем его
	$conn->close();
	//Функция die() прекращает дальнейшее выполнение текущего скрипта	
	die();
}

//Т.к. больше соединение нам пока не нужно, закрываем его
$conn->close();   
?>

Пример 2.1.8.3. Создание таблицы

Осталось добавить в таблицу какие-нибудь данные (см. пример 2.1.8.4).

<?php
//Оформим аргументы, которые необходимо передать конструктору 
//mysqli::__construct, в виде переменных

//Имя хоста задаем как "localhost", хотя можем входить с любого компьютера
$servername = "localhost";
//Входим под именем администратора  
$username = "administrator"; 
//Не забываем про пароль
$password = "12345";
//Указываем базу данных, к которой будем  подключаться
$db_name = "belarusweb_users";
//Создаем объект соединения с MySQL	
$conn = new mysqli ($servername, $username, $password, $db_name);

//Если произойдет ошибка соединения, то выведем строку с описанием последней ошибки
//подключения, использовав свойство объекта mysqli->connect_error и прервем скрипт
if ($conn->connect_error){   
   //Функция die() выводит сообщение и прекращает выполнение текущего скрипта
   echo "Ошибка соединения с сервером MySQL: ".$conn->connect_error."<br>";
	//Функция die() выводит сообщение и прекращает выполнение текущего скрипта	
	die("Соединение установлено не было.");
}
//Установим кодировку данных для данного соединения с MySQL, чтобы русские символы правильно отображались в базе.
$conn->set_charset("utf8"); 

//Чтобы не использовать повторно большие куски кода, оформим класс 
class sql_msg{
	//Статический метод можно будет вызывать без создания объекта
	public static function result($sql){
		//Будем использовать глобальную переменную
		global $conn;
		//Выполняем запрос и если он прошел успешно, сообщаем об успехе
		if($conn->query($sql) === true){
			echo "Операция успешно выполнена.<br>";     
		}else{
			//Прекращаем выполнение скрипта и выводим строку с описанием ошибки
			echo "Ошибка операции: ".$conn->error.".";   
		}
	}
}

//В первых скобках перечисляем имена столбцов, во вторых соответствующие значения
//Порядок столбцов может быть любым, но тогда нужно поменять и порядок соответствующих 
//им значений. Количество значений должно быть равным количеству столбцов
$sql_1 = "INSERT INTO our_users(first_name,	last_name, age, sex, reg_mail)
			values('Сергей', 'Петров', 30, 'мужской', 'my_mail_1@tut.by')";   
//Выполняем запрос и если он прошел успешно, сообщаем об успехе
sql_msg::result($sql_1);

$sql_2 = "INSERT INTO our_users(first_name,	last_name, age, sex, reg_mail)
			values('Сергей', 'Иванов', 33, 'мужской', 'my_mail_3@tut.by')"; 
sql_msg::result($sql_2);

$sql_3 = "INSERT INTO our_users(first_name,	last_name, age, sex, reg_mail)
			values('Иван', 'Иванов', 23, 'мужской', 'my_mail_21@tut.by')"; 
sql_msg::result($sql_3);

$sql_4 = "INSERT INTO our_users(first_name,	last_name, age, sex, reg_mail)
			values('Елена', 'Сидорова', 23, 'женский', 'my_mail_10@tut.by')"; 
sql_msg::result($sql_4);

$sql_5 = "INSERT INTO our_users(first_name,	last_name, age, sex, reg_mail)
			values('Наталья', 'Осипович', 44, 'женский', 'my_mail_15@tut.by')"; 
sql_msg::result($sql_5);

//Т.к. больше соединение нам пока не нужно, закрываем его
$conn->close();   
?>

Пример 2.1.8.4. Добавление в таблицу данных о пользователях

Прежде, чем идти дальше, еще раз посмотрите в официальном справочнике информацию по использованным нами методам и свойствам модуля MySQLi:

  • mysqli::__construct() – конструктор, устанавливает новое соединение с сервером MySQL;
  • mysqli::$connect_error – свойство, возвращает описание последней ошибки подключения, в отличие от свойства mysqli::$connect_errno, которое возвращает код ошибки, а не описание;
  • mysqli::set_charset() – метод, задает набор символов по умолчанию;
  • mysqli::query() – метод, выполняет запрос к базе данных;
  • mysqli::$error – свойство, возвращает строку с описанием последней ошибки, в отличие от свойства mysqli::$errno, которое возвращает код ошибки, а не описание;
  • mysqli::close() – метод, закрывает ранее открытое соединение с базой данных;

Обработка данных результирующего набора

После заполнения таблицы данными и просмотре ее содержимого в phpMyAdmin она будет иметь вид, показанный на рис. 2.1.8.5.

Рис. 2.1.8.5. Таблица с данными пользователей

Если данные из таблицы понадобится извлечь для дальнейшего использования, например, для отображения данных пользователя на его персональной странице, нужно отправить соответствующий запрос на выборку необходимых данных при помощи метода mysqli::query(), который в случае успешного выполнения запросов SELECT, SHOW, DESCRIBE или EXPLAIN вернет объект mysqli_result, представлющий собой результирующий набор данного запроса. Далее, при помощи свойств и методов mysqli_result, данные результирующего набора могут быть обработаны, а затем использованы по своему усмотрению (см. пример 2.1.8.6).

<?php
//Оформим аргументы, которые необходимо передать конструктору 
//mysqli::__construct, в виде переменных

//Имя хоста задаем как "localhost", хотя можем входить с любого компьютера
$servername = "localhost";
//Входим под именем администратора  
$username = "administrator"; 
//Не забываем про пароль
$password = "12345";
//Указываем базу данных, к которой будем  подключаться
$db_name = "belarusweb_users";
//Создаем объект соединения с MySQL	
$conn = new mysqli ($servername, $username, $password, $db_name);

//Если произойдет ошибка соединения, то выведем строку с описанием последней ошибки
//подключения, использовав свойство объекта mysqli->connect_error и прервем скрипт
if ($conn->connect_error){   
   //Функция die() выводит сообщение и прекращает выполнение текущего скрипта
   echo "Ошибка соединения с сервером MySQL: ".$conn->connect_error."<br>";
	//Функция die() выводит сообщение и прекращает выполнение текущего скрипта	
	die("Соединение установлено не было.");
}
//Установим кодировку данных для данного соединения с MySQL, 
//чтобы русские символы правильно отображались в базе.
$conn->set_charset("utf8"); 

//Чтобы не использовать повторно большие куски кода, оформим класс 
class sql_msg{
	//Статический метод можно будет вызывать без создания объекта
	public static function result($rslt){
		//Будем использовать глобальную переменную
		global $conn;
		//Если запрос не удался
		if($rslt === false){
			//Прекращаем выполнение скрипта и выводим строку с описанием ошибки
			echo "Ошибка операции: ".$conn->error.".";   
			//Т.к. соединение нам пока не нужно, закрываем его
			$conn->close();
			//Функция die() прекращает дальнейшее выполнение текущего скрипта	
			die();
		}
	}
}
echo 'Первый пример.<br>';

//.................. 1. mysqli_result::fetch_row()  ...........................

//Выберем все строки, в столбце first_name которых присутствует значение 'Сергей'
$sql_1 = "select * from our_users where first_name='Сергей'"; 
//Выполняем запрос, а результат присваеваем переменной
$rslt_1=$conn->query($sql_1);
//Если запрос прошел успешно, сообщаем об успехе
sql_msg::result($rslt_1);

//mysqli_result::$num_rows возвращает число рядов результирующей выборки
//Так что цикл выведет все строки подряд
for($i=0; $i<$rslt_1->num_rows; $i++){
	//mysqli_result::fetch_row() возвращает строку выборки в виде массива, т.е. 
	//значения каждой колонки строки становятся элементами массива
	$m = $rslt_1->fetch_row();
	//Выведем через пробел все значения массива (т.е. колонок текущей строки)
	for($k=0; $k<count($m); $k++){
		echo $m[$k].' &nbsp ';
	}
	//Значения каждой новой строки результирующего набора выведем на новой строке
	echo '<br>';
}

//Освобождаем память занятую результатами запроса
$rslt_1->free();
//Значения каждого нового запроса выведем на новой строке
echo '<br>Второй пример.<br>';

//.................. 2. mysqli_result::fetch_assoc()  ...........................

//Выберем все строки, в столбце first_name которых присутствует значение 'Сергей'
$sql_1 = "select * from our_users where first_name='Сергей'"; 
//Выполняем запрос, а результат присваеваем переменной
$rslt_1=$conn->query($sql_1);
//Если запрос прошел успешно, сообщаем об успехе
sql_msg::result($rslt_1);

//mysqli_result::$num_rows возвращает число рядов результирующей выборки
//Так что цикл выведет все строки подряд
for($i=0; $i<$rslt_1->num_rows; $i++){
	//mysqli_result::fetch_assoc() возвращает строку выборки в виде ассоциативного 
	//массива, т.е. значения каждой колонки строки становятся элементами массива, 
	//в котором ключи элементов массива соответствуют именам колонок строки
	$m = $rslt_1->fetch_assoc();
	
	//Выведем через пробел все значения массива (т.е. колонок текущей строки)
	foreach($m as $key=>$value){
		echo $m[$key].' &nbsp ';
	}
	//Значения каждой новой строки результирующего набора выведем на новой строке
	echo '<br>';
}

//Освобождаем память занятую результатами запроса
$rslt_1->free();
//Значения каждого нового запроса выведем на новой строке
echo '<br>Третий пример.<br>';
  
//.................. 3. mysqli_result::fetch_array()  ...........................

//Выберем все строки, в столбце first_name которых присутствует значение 'Сергей'
$sql_1 = "select * from our_users where first_name='Сергей'"; 
//Выполняем запрос, а результат присваеваем переменной
$rslt_1=$conn->query($sql_1);
//Если запрос прошел успешно, сообщаем об успехе
sql_msg::result($rslt_1);

//Сместим указатель на 1-ю строку набора при помощи mysqli_result::data_seek() 
$rslt_1->data_seek(0);

//mysqli_result::fetch_array(MYSQLI_ASSOC | MYSQLI_NUM | MYSQLI_BOTH) возвращает 
//строку выборки в виде ассоциативного массива, обычного или сразу обоих  
$m = $rslt_1->fetch_array(MYSQLI_ASSOC);

//Выведем через пробел все значения массива, используя именованные ключи
foreach($m as $key=>$value){
	echo $m[$key].' &nbsp ';
}
//Значения следующей строки результирующего набора выведем на новой строке
echo '<br>';

//Сместим указатель на последнюю строку набора 
$rslt_1->data_seek($rslt_1->num_rows-1);

//mysqli_result::fetch_array(MYSQLI_ASSOC | MYSQLI_NUM | MYSQLI_BOTH) возвращает 
//строку выборки в виде ассоциативного массива, обычного или сразу обоих  
$m = $rslt_1->fetch_array(MYSQLI_NUM);

//Выведем через пробел все значения массива используя числовые ключи
for($i=0; $i<$rslt_1->field_count; $i++){
	echo $m[$i].' &nbsp ';
}
//Освобождаем память занятую результатами запроса
$rslt_1->free();

//Т.к. больше соединение нам пока не нужно, закрываем его
$conn->close();   
?>	

Пример 2.1.8.6. Извлечение данных результирующего набора

Еще раз посмотрите в официальном справочнике информацию по использованным нами методам и свойствам модуля MySQLi:

  • mysqli_result::$num_rows – свойство, возвращает число рядов в результирующей выборке;
  • mysqli_result::data_seek – метод, перемещает указатель результата на выбранную строку;
  • mysqli_result::fetch_row() – метод, выбирает одну строку данных из результирующего набора и возвращает ее в виде массива, в котором индексы элементов соответствуют номерам столбцов (начиная с 0);
  • mysqli_result::fetch_assoc() – метод, выбирает одну строку данных из результирующего набора и возвращает ее в виде ассоциативного массива, в котором ключи элементов массива соответствуют именам колонок строки;
  • mysqli_result::fetch_array() – метод, является расширенной версией предыдущих двух методов; метод выбирает одну строку данных из результирующего набора и возвращает ее в виде массива указанного вида: ассоциативного, обычного или сразу обоих;
  • mysqli_result::$field_count – свойство, возвращает число полей (столбцов) в результирующей выборке;
  • mysqli_result::free – свойство, освобождает память занятую результатами запроса.

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