Пакет · cdo

Быстрый старт

За пять минут вы пройдёте от учётных данных до полного цикла: определите конфиг, откроете соединение, вставите пользователя и прочитаете его id, обновите его, запросите с условием и удалите. Каждое значение привязывается — вы никогда не склеиваете SQL.

Время ~5 минУровень НачальныйТребования PHP 8.3+, база данных

Что вы построите

Небольшой жизненный цикл над таблицей users: подключение → insert → update → запрос → delete. Возьмём PostgreSQL, но единственная строка, которая меняется для MySQL/MariaDB, — это базовый класс конфигурации; вызовы DML идентичны.

Предположим таблицу вида:

sql
CREATE TABLE users (
  id    SERIAL PRIMARY KEY,
  name  TEXT NOT NULL,
  email TEXT UNIQUE NOT NULL,
  age   INT
);

Шаг 1 — Определите конфиг

app/Db/AppDb.php
<?php

namespace App\Db;

use Flytachi\Winter\Cdo\Config\PgDbConfig;

class AppDb extends PgDbConfig
{
  public function setUp(): void
  {
      $this->host     = '127.0.0.1';
      $this->port     = 5432;
      $this->database = 'myapp';
      $this->username = 'postgres';
      $this->password = 'secret';
  }
}

Шаг 2 — Получите соединение

php
use Flytachi\Winter\Cdo\ConnectionPool;
use App\Db\AppDb;

$cdo = ConnectionPool::db(AppDb::class);

ConnectionPool создаёт конфиг один раз и лениво открывает сокет PDO при первом использовании. Вызовите его снова где угодно — вернётся то же соединение.

Шаг 3 — Вставьте и получите id

insert() возвращает сгенерированный первичный ключ. На PostgreSQL и MariaDB используется INSERT ... RETURNING; на MySQL происходит откат к lastInsertId().

php
$id = $cdo->insert('users', [
  'name'  => 'Alice',
  'email' => 'alice@example.com',
  'age'   => 30,
]);

echo $id; // напр. 1

Колонки со значением NULL пропускаются

Любой ключ со значением null выбрасывается из INSERT, позволяя колонке принять значение по умолчанию из базы (или автогенерируемый id). Передавайте только то, что действительно хотите задать.

Шаг 4 — Обновите с условием

Третий аргумент — это условие Qb для секции WHERE. update() возвращает количество затронутых строк.

php
use Flytachi\Winter\Cdo\Qb;

$affected = $cdo->update('users',
  ['name' => 'Alice Smith'],
  Qb::eq('id', $id)
);

echo $affected; // 1

Шаг 5 — Запросите через нижележащий PDO

CDO является PDO, поэтому используйте prepare / query / fetchAll напрямую. Соедините фрагмент Qb с его привязками:

php
$where = Qb::and(
  Qb::gte('age', 18),
  Qb::like('email', '%@example.com'),
);

$stmt = $cdo->prepare("SELECT * FROM users WHERE " . $where->getQuery());
foreach ($where->getBinds() as $bind) {
  $stmt->bindValue($bind->getName(), $bind->getValue());
}
$stmt->execute();

$rows = $stmt->fetchAll(); // режим выборки по умолчанию — FETCH_ASSOC

Шаг 6 — Удалите

delete() тоже принимает Qb и возвращает количество удалённых строк:

php
$deleted = $cdo->delete('users', Qb::eq('id', $id));

echo $deleted; // 1

Всё целиком

demo.php
<?php

require 'vendor/autoload.php';

use Flytachi\Winter\Cdo\ConnectionPool;
use Flytachi\Winter\Cdo\Qb;
use App\Db\AppDb;

$cdo = ConnectionPool::db(AppDb::class);

// создание
$id = $cdo->insert('users', [
  'name'  => 'Alice',
  'email' => 'alice@example.com',
  'age'   => 30,
]);

// обновление
$cdo->update('users', ['name' => 'Alice Smith'], Qb::eq('id', $id));

// чтение
$stmt = $cdo->prepare('SELECT * FROM users WHERE ' . Qb::eq('id', $id)->getQuery());
foreach (Qb::eq('id', $id)->getBinds() as $b) {
  $stmt->bindValue($b->getName(), $b->getValue());
}
$stmt->execute();
$user = $stmt->fetch();

// удаление
$cdo->delete('users', Qb::eq('id', $id));

Дальше