Привязка параметров
Каждое значение, которое пишет CDO, проходит через
CDOStatement::bindTypedValue(), выбирающий константу PDO::PARAM_* по типу PHP
значения. Именно это позволяет передавать bool, int, массив или DateTime и
получать корректный SQL без кастов — вот как именно он решает.
Переключатель типов
bindTypedValue($parameter, $value) читает gettype($value) и диспетчеризует:
| Тип PHP | Тип PDO | Преобразование |
|---|---|---|
null |
PARAM_NULL |
— |
bool |
PARAM_BOOL |
— |
int |
PARAM_INT |
— |
array |
PARAM_STR |
сначала json_encode($value) |
object |
PARAM_STR |
сериализуется через valObject() (ниже) |
float, string, прочее |
PARAM_STR |
привязывается как есть |
Это работает для значений колонок insert/upsert, значений SET в update и
каждой привязки Qb — единый согласованный путь.
Почему важны булевы и целые
Привязка bool как PARAM_BOOL, а int как PARAM_INT (а не позволять всему
скатываться к строке) держит PostgreSQL довольным boolean-колонками и позволяет
числовым сравнениям корректно использовать индексы. Это разница между
WHERE active = true и драйвером, давящимся на '1'.
Массивы становятся JSON
Значение-массив проходит json_encode перед привязкой, поэтому колонка JSON/JSONB
получает валидный JSON без лишней работы:
$cdo->update('products',
['attributes' => ['color' => 'red', 'size' => 'M']],
Qb::eq('id', 42)
);
// attributes привязано как '{"color":"red","size":"M"}'Сериализация объектов (valObject)
Когда значение — объект, valObject() преобразует его в скаляр, проверяя
интерфейсы в таком порядке — побеждает первое совпадение:
| Приоритет | Интерфейс / тип | Преобразование |
|---|---|---|
| 1 | JsonSerializable |
$value->jsonSerialize() |
| 2 | Stringable |
(string) $value |
| 3 | DateTimeInterface |
$value->format('Y-m-d H:i:s') |
| 4 | BackedEnum |
$value->value |
| 5 | что угодно ещё | serialize($value) (сериализация PHP) |
$cdo->insert('events', [
'occurred_at' => new DateTimeImmutable('2026-07-01 12:00:00'), // → '2026-07-01 12:00:00'
'status' => Status::Active, // BackedEnum → его ->value
'payload' => $dtoImplementingJsonSerializable, // → jsonSerialize()
]);У порядка есть последствия
Поскольку JsonSerializable проверяется первым, объект, являющийся одновременно
JsonSerializable и DateTimeInterface, кодируется в JSON, а не форматируется
как дата-время. А запасной вариант приоритета 5 — это PHP serialize(), что редко
нужно колонке. Реализуйте Stringable или JsonSerializable на своих
объектах-значениях, чтобы они попадали на намеренную ветку, а не на запасной
serialize.
Явная привязка и переигрывание
CDOStatement также предоставляет более низкоуровневое управление:
bindValue($param, $value, $type = PDO::PARAM_STR)— привязать с явным PDO-типом, минуя определение. Каждая привязка (типизированная или явная) записывается.getBindings()— записанные тройки[param, value, type].updateStm(PDOStatement $stmt)— подставить свежеподготовленный statement и переиграть на нём каждую записанную привязку. Именно это делает statement переживающим переподключение: значения заново применяются дословно к новому дескриптору.
Чтение обратно
Привязка — это забота пути записи. Когда вы читаете унаследованными методами PDO,
значения возвращаются такими, как их отдаёт драйвер — JSON-колонка это строка,
которую вы сами json_decode, дата-время это строка. CDO не обращает
valObject() при чтении.
Связанное
- Конфигурация — список методов
CDOStatement - Вставка записей — где входят значения
- Модель работы — значения едут рядом с SQL, не внутри него