97 lines
3.1 KiB
PHP
97 lines
3.1 KiB
PHP
<?php
|
||
/**
|
||
* @package Bicycle
|
||
* @author Egor Isaev
|
||
* @description Statement.php
|
||
* @copyright (c) 07/08/2026
|
||
*/
|
||
|
||
namespace Services\DataBase\Classes;
|
||
|
||
use PDO;
|
||
use PDOStatement;
|
||
|
||
/**
|
||
* Расширение PDOStatement, подключается через PDO::ATTR_STATEMENT_CLASS
|
||
* (см. PdoDriver::connect()). Добавляет showQuery()/sq() — PDOStatement::debugDumpParams()
|
||
* печатает в stdout, а не возвращает строку, поэтому значения bind-параметров
|
||
* копятся вручную (bindValue()/execute() переопределены) и подставляются в SQL сами.
|
||
*/
|
||
class Statement extends PDOStatement
|
||
{
|
||
/** @var array<int|string,mixed> Значения, забинженные через bindValue()/execute() */
|
||
protected array $_bound_params = [];
|
||
|
||
/**
|
||
* Конструктор вызывается только изнутри PDO (PDO::ATTR_STATEMENT_CLASS) — не создавать напрямую.
|
||
*
|
||
* @param PdoDriver $driver Владелец, нужен для quote() в showQuery()
|
||
*/
|
||
protected function __construct(protected PdoDriver $driver)
|
||
{
|
||
}
|
||
|
||
/**
|
||
* @inheritDoc
|
||
*/
|
||
public function bindValue(int|string $param, mixed $value, int $type = PDO::PARAM_STR): bool
|
||
{
|
||
$this->_bound_params[$param] = $value;
|
||
|
||
return parent::bindValue($param, $value, $type);
|
||
}
|
||
|
||
/**
|
||
* @inheritDoc
|
||
*/
|
||
public function execute(?array $params = null): bool
|
||
{
|
||
foreach ($params ?? [] as $key => $value) {
|
||
$this->_bound_params[$key] = $value;
|
||
}
|
||
|
||
return parent::execute($params);
|
||
}
|
||
|
||
/**
|
||
* Возвращает SQL с подставленными вместо плейсхолдеров значениями — только для дебага
|
||
* (не для реального выполнения: значения квотируются через PDO::quote(), не защищают от всего,
|
||
* на что рассчитана честная подготовленная подстановка).
|
||
*
|
||
* @return string
|
||
* @throws \System\Classes\MyException
|
||
*/
|
||
public function showQuery(): string
|
||
{
|
||
$sql = $this->queryString;
|
||
|
||
foreach ($this->_bound_params as $key => $value) {
|
||
$quoted = is_int($value) || is_float($value) ? (string) $value : $this->driver->pdo()->quote((string) $value);
|
||
|
||
if (is_int($key)) {
|
||
$pos = strpos($sql, '?');
|
||
|
||
if ($pos !== false) {
|
||
$sql = substr_replace($sql, $quoted, $pos, 1);
|
||
}
|
||
} else {
|
||
$placeholder = str_starts_with((string) $key, ':') ? $key : ':' . $key;
|
||
$sql = str_replace($placeholder, $quoted, $sql);
|
||
}
|
||
}
|
||
|
||
return $sql;
|
||
}
|
||
|
||
/**
|
||
* Алиас showQuery() для быстрого дебага.
|
||
*
|
||
* @return string
|
||
* @throws \System\Classes\MyException
|
||
*/
|
||
public function sq(): string
|
||
{
|
||
return $this->showQuery();
|
||
}
|
||
}
|