Создание, модификация и удаление MySQL таблиц в PHP

Раздел: Программирование на PHP -> Работа с таблицами

Основной рекомендуемый способ: PDO

Как безопасно и гибко выполнять запросы к таблицам MySQL из PHP?

PDO (PHP Data Objects) предоставляет унифицированный интерфейс и поддержку подготовленных выражений. Это предпочтительный метод для новых проектов.

$dsn = 'mysql:host=localhost;dbname=test;charset=utf8mb4';
$pdo = new PDO($dsn, 'root', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

Создание таблицы:

$pdo->exec("CREATE TABLE IF NOT EXISTS products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

Вставка данных с подготовленным выражением:

$stmt = $pdo->prepare("INSERT INTO products (name, price) VALUES (:name, :price)");
$stmt->execute([':name' => 'Ноутбук', ':price' => 799.99]);

Изменение структуры таблицы:

$pdo->exec("ALTER TABLE products ADD COLUMN description TEXT AFTER price");

Удаление таблицы:

$pdo->exec("DROP TABLE IF EXISTS products");

Типичные ошибки:

  • Не указан PDO::ATTR_ERRMODE в исключениях - трудно отловить ошибки.
  • Использование неэкранированных переменных в SQL - приводит к инъекциям.
  • Забыли проверить успешность exec() - возвращает количество затронутых строк, а не boolean.
  • Ошибка подключения: проверьте DSN, имя пользователя и пароль.

Вариант: расширение mysqli (объектный стиль)

Как использовать объектно-ориентированный интерфейс mysqli?

Цель: работа в окружениях, где PDO недоступно или проект уже использует mysqli. Пример подключения и выборки:

$mysqli = new mysqli('localhost', 'root', '', 'test');
if ($mysqli->connect_errno) { echo "Ошибка подключения: {$mysqli->connect_error}"; exit; }
$result = $mysqli->query("SELECT id, name FROM products");
while ($row = $result->fetch_assoc()) { echo $row['name'] . "\n"; }

Проблемы: при использовании query() без подготовки возможны SQL-инъекции. Необходимо использовать prepare() и bind_param() для переменных. Решение: $stmt = $mysqli->prepare('SELECT * FROM products WHERE id = ?'); $stmt->bind_param('i', $id); $stmt->execute();.

Вариант: расширение mysqli (процедурный стиль)

Как быстро написать скрипт с mysql функциями?

Цель: простые скрипты, где не требуется ООП. Пример:

$link = mysqli_connect('localhost', 'root', '', 'test');
if (!$link) { die('Ошибка: ' . mysqli_connect_error()); }
$result = mysqli_query($link, "SELECT * FROM products");
while ($row = mysqli_fetch_assoc($result)) { ... }

Ошибки: не закрыто соединение, не проверены ошибки запроса. Устаревшие функции mysql_* больше не поддерживаются. Решение: использовать mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) для автоматической генерации исключений.

Вариант: устаревшее расширение mysql (не рекомендуется)

Почему не стоит использовать функции mysql_* в новых проектах?

Цель: поддержка старого кода, но для нового не использовать. Пример:

$link = mysql_connect('localhost', 'root', '');
mysql_select_db('test', $link);
$result = mysql_query('SELECT * FROM products', $link);
while ($row = mysql_fetch_assoc($result)) { ... }

Проблемы: расширение удалено из PHP 7.0, отсутствует поддержка подготовленных выражений, уязвимо к SQL-инъекциям. Решение: мигрировать на PDO или mysqli.

Вариант: использование ORM (например, Eloquent)

Как абстрагироваться от SQL-запросов при работе с таблицами?

Цель: ускорение разработки, автоматическое создание таблиц через миграции, удобное управление связями. Пример модели в Laravel:

class Product extends Model {
    protected $table = 'products';
    protected $fillable = ['name', 'price'];
}
$product = Product::create(['name' => 'Телефон', 'price' => 599.99]);

Проблемы: ORM может скрывать оптимизацию запросов, требуется изучить синтаксис ORM. Для сложных запросов может быть медленнее. Решение: использовать raw-запросы через DB::select() при необходимости.

Дополнительные расширенные примеры работы с таблицами через PDO:

Создание таблицы с внешним ключом и транзакция

Пример
try {
    $pdo->beginTransaction();
    $pdo->exec("CREATE TABLE categories (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(50) NOT NULL
    ) ENGINE=InnoDB");
    $pdo->exec("CREATE TABLE products (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(100) NOT NULL,
        category_id INT,
        FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
    ) ENGINE=InnoDB");
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Ошибка: " . $e->getMessage();
}
(таблицы созданы, ошибок нет)

Выборка с использованием fetchColumn

Пример
$stmt = $pdo->query("SELECT COUNT(*) FROM products");
$count = $stmt->fetchColumn();
echo "Всего товаров: $count";
Всего товаров: 5

Массовая вставка с подготовленными выражениями

Пример
$products = [['name' => 'A', 'price' => 10], ['name' => 'B', 'price' => 20]];
$stmt = $pdo->prepare("INSERT INTO products (name, price) VALUES (:name, :price)");
foreach ($products as $p) {
    $stmt->execute($p);
}
echo "Добавлено: " . count($products);
Добавлено: 2

Обновление с использованием named placeholders

Пример
$stmt = $pdo->prepare("UPDATE products SET price = :price WHERE id = :id");
$stmt->execute([':price' => 899.99, ':id' => 1]);
echo $stmt->rowCount() . " строк обновлено";
1 строк обновлено

Удаление с условием

Пример
$stmt = $pdo->prepare("DELETE FROM products WHERE id = :id");
$stmt->execute([':id' => 10]);
if ($stmt->rowCount() === 0) { echo "Запись не найдена"; }
Запись не найдена

Использование fetchAll с режимом FETCH_CLASS

Пример
class Product {
    public $id;
    public $name;
    public $price;
}
$stmt = $pdo->query("SELECT id, name, price FROM products");
$products = $stmt->fetchAll(PDO::FETCH_CLASS, 'Product');
foreach ($products as $p) { echo $p->name . " - " . $p->price; }
Ноутбук - 799.99

Запрос с JOIN и подготовленными параметрами

Пример
$stmt = $pdo->prepare("SELECT p.name, c.name AS category FROM products p JOIN categories c ON p.category_id = c.id WHERE c.id = ?");
$stmt->execute([1]);
$rows = $stmt->fetchAll();
print_r($rows);
Array ( [0] => Array ( [name] => Ноутбук [category] => Электроника ) )

Получение ID последней вставленной записи

Пример
$pdo->exec("INSERT INTO categories (name) VALUES ('Новая категория')");
$id = $pdo->lastInsertId();
echo "ID новой категории: $id";
ID новой категории: 3

Работа с MySQL таблицами в PHP - comments

En
Mysql таблицы php (php)