MySQL — это жвачка: дешево, сердито, но надоедает. Postgres — это как виски без закуски: поначалу жжёт, потом начинает нравиться, а потом ты уже не понимаешь, как вообще жил без нормальных индексов по jsonb и адекватных транзакций.

Laravel официально дружит с Postgres, но не обманывайся: кое-где придётся лезть в DB::raw() и писать руками, потому что Eloquent не знает про половину плюшек.

Шаг 1. PostgreSQL под задницу

Ставишь Postgres. Да, с их офсайта. Да, со всеми этими танцами вокруг pg_hba.conf и паролей. И готовься к тому, что он будет жрать память, как голодный кот.

Шаг 2. Настройка .env

В .env всё по стандарту:

DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=your_database_name
DB_USERNAME=your_username
DB_PASSWORD=your_password

Если в MySQL ты мог прощать себе лень, то в Postgres всё строже: забудешь схему или права — и лови «permission denied».

Шаг 3. Миграции и таблицы

Artisan миграции те же, но Postgres даст по рукам за твой расслабленный стиль. Например, json тут нормальный (jsonb), а не декорация. Уникальные индексы работают как надо, и можно строить составные ключи без костылей.

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->jsonb('meta')->nullable();
    $table->timestamps();
});

И да, Postgres тебе позволит завести поля под массивы, UUID и прочие радости. MySQL тут нервно курит в углу.

Шаг 4. Eloquent и суровая правда

Eloquent работает. Но это максимум 70% от того, что Postgres умеет. Всё, что связано с jsonb, full-text search или CTE — придётся тянуть через DB::raw().

$users = DB::table('users')
    ->select(DB::raw("meta->>'city' as city, count(*)"))
    ->groupBy('city')
    ->get();

Красота? Да. Поддержка из коробки? Хрен там.

Шаг 5. Сложные запросы — CTE в бой

Postgres умеет CTE (WITH ... AS) так, как MySQL даже не мечтает. Laravel же делает вид, что не в курсе. Придётся писать руками:

$users = DB::select("
    WITH active AS (
        SELECT * FROM users WHERE status = 'active'
    )
    SELECT count(*) FROM active
");

Нормально работает. Но забудь про красивые Eloquent-цепочки, тут суровый SQL в чистом виде.

Шаг 6. Фишки PostgreSQL

  • jsonb — хранение структурированных данных, которые можно фильтровать без костылей.
  • array — да, можно прямо массивы в колонке.
  • uuid — нормальный идентификатор, а не автоинкрементная костыльщина.
  • full-text search — встроенный поиск, который не требует городить Elasticsearch ради пары запросов.

Laravel про всё это слышал, но делает вид, что «позже прикрутим». Так что готовься писать руками и поднимать абстракцию над Query Builder.

Итог: Postgres — зверь в клетке

Laravel и Postgres — нормальная пара, если у тебя проект не на уровне «блог на 3 страницы». Тут можно строить реально сложные штуки, и база не будет умирать от первого же join-а.

Но если ты думаешь, что Eloquent и магические методы решат за тебя всё — забудь. Postgres раскрывается только тогда, когда ты перестаёшь бояться DB::raw(), ручных индексов и SQL, который не влезает в одну строку.