PHP и PostgreSQL: мощный дуэт для веб-разработки

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему PHP и PostgreSQL — это любовь с первого запроса?

Мир веб-разработки полон стереотипов. Один из них гласит: «PHP дружит только с MySQL». Доля правды в этом есть, но только до тех пор, пока вы не попробуете связку PHP и PostgreSQL. Это как перейти с велосипеда на спортивный мотоцикл: всё те же колёса, но скорость, манёвренность и надёжность совершенно иные.

PostgreSQL — это не просто база данных. Это объектно-реляционный монстр, который умеет работать с JSON, геоданными, полнотекстовым поиском и сложнейшими транзакциями. А PHP — идеальный дирижёр для этого оркестра. В этом руководстве мы разберём всё: от установки драйвера до написания production-ready кода. Поехали!

1. Установка и настройка: готовим инструменты

Прежде чем писать код, убедимся, что PHP знает о существовании PostgreSQL. В большинстве современных дистрибутивов PHP (например, XAMPP, OpenServer, Docker) расширение pdo_pgsql уже есть, но его нужно активировать.

1.1. Включаем расширение в php.ini

Откройте ваш php.ini и раскомментируйте (уберите точку с запятой в начале) строку:

extension=pdo_pgsql

Если вы используете Linux, установка выглядит так:

sudo apt-get install php-pgsql
sudo service apache2 restart  # или nginx + php-fpm

1.2. Создаём базу и пользователя

Заходим в консоль PostgreSQL:

sudo -u postgres psql

Теперь создадим базу данных и пользователя для нашего проекта:

CREATE DATABASE pythonlib_blog;
CREATE USER myapp WITH PASSWORD 'SuperSecret123';
GRANT ALL PRIVILEGES ON DATABASE pythonlib_blog TO myapp;
\q

Готово. Теперь у нас есть база pythonlib_blog и пользователь myapp.

2. Первое подключение: PDO как стандарт

Никогда не используйте старые функции pg_connect(). В современном PHP есть PDO (PHP Data Objects) — единый интерфейс для работы с разными БД. Он безопаснее, удобнее и поддерживает подготовленные запросы.

2.1. Класс-обёртка для подключения

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

<?php

class Database {
    private static ?PDO $instance = null;
    private const DB_HOST = 'localhost';
    private const DB_PORT = 5432;
    private const DB_NAME = 'pythonlib_blog';
    private const DB_USER = 'myapp';
    private const DB_PASS = 'SuperSecret123';

    public static function getConnection(): PDO {
        if (self::$instance === null) {
            $dsn = "pgsql:host=" . self::DB_HOST . ";port=" . self::DB_PORT . ";dbname=" . self::DB_NAME;
            try {
                self::$instance = new PDO($dsn, self::DB_USER, self::DB_PASS, [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false,
                ]);
            } catch (PDOException $e) {
                die("Connection failed: " . $e->getMessage());
            }
        }
        return self::$instance;
    }
}

Почему это круто? Во-первых, синглтон — мы не создаём новое подключение при каждом запросе. Во-вторых, ATTR_EMULATE_PREPARES => false заставляет PostgreSQL использовать настоящие подготовленные запросы, а не эмуляцию на стороне PHP. Это повышает производительность и безопасность.

3. CRUD-операции: создаём, читаем, обновляем, удаляем

Теперь самое мясо. Допустим, у нас есть таблица articles для статей на pythonlib.ru.

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

Выполните этот SQL в вашей БД (через psql или админку):

CREATE TABLE articles (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    author VARCHAR(100) DEFAULT 'Admin',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

3.2. INSERT (Создание записи)

<?php
require_once 'Database.php';

$pdo = Database::getConnection();

$sql = "INSERT INTO articles (title, content, author) VALUES (:title, :content, :author)";
$stmt = $pdo->prepare($sql);

$stmt->execute([
    ':title' => 'PHP и PostgreSQL: полное руководство',
    ':content' => 'Подробная статья о работе с PostgreSQL из PHP...',
    ':author' => 'Команда PythonLib'
]);

echo "Статья добавлена с ID: " . $pdo->lastInsertId();

Обратите внимание: мы используем именованные плейсхолдеры (:title). Это защищает от SQL-инъекций. Никогда не подставляйте переменные напрямую в строку запроса!

3.3. SELECT (Чтение данных)

Получим все статьи автора «Admin»:

<?php
$pdo = Database::getConnection();

$sql = "SELECT id, title, created_at FROM articles WHERE author = :author ORDER BY created_at DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute([':author' => 'Admin']);
$articles = $stmt->fetchAll();

foreach ($articles as $article) {
    echo "<h3>" . htmlspecialchars($article['title']) . "</h3>";
    echo "<p>Опубликовано: " . $article['created_at'] . "</p>";
}

Функция htmlspecialchars() — обязательный минимум для защиты от XSS-атак.

3.4. UPDATE (Обновление)

<?php
$pdo = Database::getConnection();

$sql = "UPDATE articles SET content = :content WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([
    ':content' => 'Обновлённое содержание статьи...',
    ':id' => 1
]);

echo "Обновлено строк: " . $stmt->rowCount();

3.5. DELETE (Удаление)

<?php
$pdo = Database::getConnection();

$sql = "DELETE FROM articles WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([':id' => 42]);

echo "Удалено строк: " . $stmt->rowCount();

4. Продвинутые фишки PostgreSQL в PHP

PostgreSQL — это не просто «положи-забери». Вот несколько killer-фич, которые вы можете использовать из PHP.

4.1. Работа с JSON

В PostgreSQL есть нативный тип JSONB. Можно хранить сложные структуры и делать запросы к ним прямо на стороне БД.

Создадим таблицу с JSONB-полем:

CREATE TABLE user_profiles (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE,
    metadata JSON                

Блоги

Рекомендаций по книгам