Структура сервера веб
Использование СУБД при разработке сайта
Достоинства:
- возможность хранения структурированной информации;
- решение проблемы совместного доступа;
- гибкость и расширяемость приложения;
- высокая скорость.
Недостатки:
- более высокие требования к платформе;
- необходимо настраивать СУБД;
- необходимо знать принципы работы с СУБД, язык SQL.
Популярные СУБД для веб-приложений:
- MySQL (MariaDB)
- PostgreSQL
- различные «большие» СУБД (Microsoft SQL Server, Oracle Database, DB2 и др.)
Основы MySQL
Простая, надежная и быстрая СУБД для малых и средних приложений. Работает на большинстве платформ. Имеет свободную и коммерческую лицензии.
Для работы с СУБД к ней надо подключиться и выбрать базу данных. По завершении работы — отключиться от СУБД. Все операции с СУБД производятся при помощи языка SQL.
c:\mysql.exe -u root -p mysql> USE php_mysql; Database changed mysql> SELECT id, name, region, residents, founded FROM city; +----+-----------+-----------------------+-----------+---------+ | id | name | region | residents | founded | +----+-----------+-----------------------+-----------+---------+ | 1 | Волгоград | Волгоградская область | 1018790 | 1589 | | 2 | Саратов | Саратовская область | 839755 | 1590 | | 3 | Астрахань | Астраханская область | 527345 | 1558 | | 4 | Элиста | Республика Калмыкия | 104238 | 1865 | | 5 | Тамбов | Тамбовская область | 281834 | 1636 | +----+-----------+-----------------------+-----------+---------+ 5 rows in set (0.00 sec) mysql> SELECT id, name, region, residents, founded FROM city WHERE id=1; +----+-----------+-----------------------+-----------+---------+ | id | name | region | residents | founded | +----+-----------+-----------------------+-----------+---------+ | 1 | Волгоград | Волгоградская область | 1018790 | 1589 | +----+-----------+-----------------------+-----------+---------+ 1 row in set (0.00 sec) mysql> INSERT INTO city SET name='Ростов-на-Дону', region='Ростовская область'; Query OK, 1 row affected, 5 warnings (0.00 sec) mysql> SELECT id, name, region, residents, founded FROM city; +----+----------------+-----------------------+-----------+---------+ | id | name | region | residents | founded | +----+----------------+-----------------------+-----------+---------+ | 1 | Волгоград | Волгоградская область | 1018790 | 1589 | | 2 | Саратов | Саратовская область | 839755 | 1590 | | 3 | Астрахань | Астраханская область | 527345 | 1558 | | 4 | Элиста | Республика Калмыкия | 104238 | 1865 | | 5 | Тамбов | Тамбовская область | 281834 | 1636 | | 6 | Ростов-на-Дону | Ростовская область | 0 | 0 | +----+----------------+-----------------------+-----------+---------+ 6 rows in set (0.00 sec) mysql> UPDATE city SET residents=1103733 WHERE id=6; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> SELECT id, name, region, residents, founded FROM city; +----+----------------+-----------------------+-----------+---------+ | id | name | region | residents | founded | +----+----------------+-----------------------+-----------+---------+ | 1 | Волгоград | Волгоградская область | 1018790 | 1589 | | 2 | Саратов | Саратовская область | 839755 | 1590 | | 3 | Астрахань | Астраханская область | 527345 | 1558 | | 4 | Элиста | Республика Калмыкия | 104238 | 1865 | | 5 | Тамбов | Тамбовская область | 281834 | 1636 | | 6 | Ростов-на-Дону | Ростовская область | 1103733 | 0 | +----+----------------+-----------------------+-----------+---------+ 6 rows in set (0.00 sec) mysql> DELETE FROM city WHERE id=6; Query OK, 1 row affected (0.00 sec) mysql> SELECT id, name, region, residents, founded FROM city; +----+-----------+-----------------------+-----------+---------+ | id | name | region | residents | founded | +----+-----------+-----------------------+-----------+---------+ | 1 | Волгоград | Волгоградская область | 1018790 | 1589 | | 2 | Саратов | Саратовская область | 839755 | 1590 | | 3 | Астрахань | Астраханская область | 527345 | 1558 | | 4 | Элиста | Республика Калмыкия | 104238 | 1865 | | 5 | Тамбов | Тамбовская область | 281834 | 1636 | +----+-----------+-----------------------+-----------+---------+ 5 rows in set (0.00 sec) mysql> QUIT;
Работа с MySQL из PHP
Работа с MySQL реализуется штатными средствами PHP через стандартное расширение. Три варианта:
1. MySQL – стандартное расширение, но в данный момент устарело. Не поддерживается в современных версиях PHP
2. MySQLi – современный аналог MySQL, более быстрый, надежный и безопасный. Рекомендуется разработчиками PHP
3. PDO – альтернативный и более сложный вариант расширения, обеспечивает работу не только с MySQL, но и с другими базами данных
MySQLi
Реализует все этапы «обычной» работы с базой данных MySQL – подключиться, выполнить действия, обработать полученные данные, отключиться.
Поддерживает объектно-ориентирванный (будет использоваться в примерах) и процедурный стили описания алгоритмов. Можно использовать любой, но не рекомендуется их смешивать.
Подключение и отключение
Выполняется только один раз
$mysqli = new mysqli( "localhost", "user", "password", "database" ); if ( $mysqli->connect_errno ) { echo "Не удалось подключиться к MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error; die(); } ... (действия и обработка) ... $mysqli->close();
Действия и обработка
Пример 1. Вывести список городов
$result = $mysqli->query( "SELECT * FROM city" ); while ( $row = $result->fetch_assoc() ) { echo $row["name"] . " - " . $row["region"] . "\n"; }
Пример 2. Вывести данные одного города
$result = $mysqli->query( "SELECT * FROM city WHERE id=1" ); if ( $row = $result->fetch_assoc() ) { echo "Город: " . $row["name"] . "\n"; echo "Регион: " . $row["region"] . "\n"; }
Пример 3. Добавить город
$sql = "INSERT INTO city SET name='Ростов-на-Дону', region='Ростовская область'"; $result = $mysqli->query( $sql ); if ( $result ) { echo "Информация успешно добавлена"; }
Пример 4. Удалить город
$sql = "DELETE FROM city WHERE id=6"; $result = $mysqli->query( $sql ); if ( $result ) { echo "Информация успешно удалена"; }
Безопасность запросов
Очень часто в запросах должна учитываться информация, полученная от пользователя.
Например, при выборе города хотим выполнить запрос:
DELETE FROM city WHERE id=6
Для этого пишем:
$sql = "DELETE FROM city WHERE id=" . $_REQUEST["city_id"];
Это опасно! Дает возможность взлома сайта через SQL-инъекцию
Передаем через $_REQUEST строку "6 OR id > 0". Тогда получаем:
DELETE FROM city WHERE id=6 OR id > 0
Это удалит все данные
Очистка переменных:
Позволяет бороться с SQL-инъекциями. Для очистки можно использовать приведение к числовым значениям или экранирование строк.
Пример 1
$sql = "DELETE FROM city WHERE id=" . (int) $_REQUEST["city_id"];
Пример 2
$name = $mysqli->escape_string( $_REQUEST["name"] ); $id = (int) $_REQUEST["id"]; $sql = "UPDATE city SET name=$name WHERE id=$id";
Подготавливаемые запросы
Два шага:
1. Готовится шаблон запроса без самих данных, обрабатывается СУБД (подготовка)
2. В СУБД передаются данные для запроса, запрос выполняется (исполнение)
Преимущества:
1. Быстро работает, когда запросы одного типа выполняются многократно
2. Исключается в принципе возможность SQL-инъекций, т.к. данные передаются отдельно от шаблона
Пример 1
$stmt = $mysqli->prepare( "DELETE FROM city WHERE id=?" ); $stmt->bind_param( "i", $id ); $result = $stmt->execute(); if ( $result ) echo "Строка успешно удалена";
Пример 2
$stmt = $mysqli->prepare( "UPDATE city SET name=? WHERE id=?" ); $stmt->bind_param( "si", $_REQUEST["name"], $_REQUEST["id"] ); $result = $stmt->execute(); if ( $result ) echo "Строка успешно изменена";
Пример 3
$stmt = $mysqli->prepare( "SELECT name, region FROM city WHERE residents > ?" ); $stmt->bind_param( "i", $_REQUEST["residents"] ); $result = $stmt->execute(); $stmt->bind_result( $name, $region ); while ( $stmt->fetch() ) { echo $name . " - " . $region . "\n"; }
Выглядит сложнее, но обеспечивает более быструю и безопасную работу. Рекомендуется к использованию.
Дополнительные возможности MySQLi
Буферизация (буферизируемые и небуферизированные запросы)
Множественные запросы
Хранимые процедуры
и др.
Контрольная работа по предыдущей лекции
Вопрос: Для чего применяются суперглобальные массивы PHP?
Алексей Н. Сергеев