- Working on revamping Ulmus bases classes

This commit is contained in:
mcndave authored and Dave Mc Nicoll committed 2026-10-22 17:24:04 +00:00
1 parent c417b00ed4
commit 25ab845886
12 files changed
+303 -52

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
<?php
namespace Ulmus\Pdo;
class Mssql extends \PDO
{
use PdoTrait;
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace Ulmus\Pdo;
class Mysql extends \PDO\Mysql
{
use PdoTrait;
}
+141
View File
@@ -0,0 +1,141 @@
<?php
namespace Ulmus\Pdo;
use PDO,
PDOStatement;
trait PdoTrait
{
public bool $executionStatus;
public int $rowCount = 0;
public mixed $lastInsertId = null;
public \Closure $onClose;
public function select(string $sql, array $parameters = []): PDOStatement
{
# static::$dump && call_user_func_array(static::$dump, [ $this->fillDebugSqlParameters($sql, $parameters) ]);
try {
if (false !== ( $statement = $this->prepare($sql) )) {
$statement->setFetchMode(\PDO::FETCH_ASSOC);
$this->execute($statement, $parameters, false);
}
}
catch (\Throwable $e) {
throw new \PdoException($e->getMessage() . " `$sql` with data:" . json_encode($parameters));
}
return $statement;
}
public function __destruct()
{
if ($this->onClose ?? null) {
call_user_func($this->onClose, $this);
}
}
public function runQuery(string $sql, array $parameters = []): ? static
{
# static::$dump && call_user_func_array(static::$dump, [ $this->fillDebugSqlParameters($sql, $parameters) ]);
try {
if (false !== ( $statement = $this->prepare($sql) )) {
return $this->execute($statement, $parameters, true);
}
}
catch(\PDOException $pdo) {
if (!str_starts_with($pdo->getMessage(), 'There is no active transaction')) {
throw $pdo;
}
}
catch (\Throwable $e) {
throw new \PdoException($e->getMessage() . " `$sql` with data:" . json_encode($parameters), (int) $e->getCode(), $e);
}
return null;
}
public function runInsertQuery(string $sql, array $parameters = []) : ? static
{
return $this->runQuery($sql, $parameters);
}
public function runUpdateQuery(string $sql, array $parameters = []) : ? static
{
return $this->runQuery($sql, $parameters);
}
public function runDeleteQuery(string $sql, array $parameters = []) : ? static
{
return $this->runQuery($sql, $parameters);
}
public function execute(PDOStatement $statement, array $parameters = [], bool $commit = true) : ? static
{
$this->executionStatus = false;
$this->lastInsertId = null;
try {
if (! $this->inTransaction()) {
$this->beginTransaction();
}
$this->bindVariables($statement, $parameters);
$this->executionStatus = $statement->execute();
if ( $this->executionStatus ) {
$this->lastInsertId = $this->lastInsertId();
$this->rowCount = $statement->rowCount();
if ( $commit ) {
$this->commit();
}
return $this;
}
else {
throw new \PDOException($statement->errorCode() . " - " . json_encode($statement->errorInfo()));
}
}
catch (\PDOException $e) {
$this->rollback();
throw $e;
}
}
protected function bindVariables(PDOStatement $statement, array &$parameters) : void
{
if ($parameters) {
if (array_is_list($parameters)) {
$parameters = array_combine(range(1, count($parameters)), array_values($parameters));
}
else {
foreach ($parameters as $key => $value) {
$type = match (strtolower(gettype($value))) {
"boolean", "integer" => Pdo::PARAM_INT,
"null" => Pdo::PARAM_NULL,
default => Pdo::PARAM_STR,
};
$statement->bindValue($key, $value, $type);
}
}
}
}
protected function fillDebugSqlParameters(string $sql, array $parameters) : string
{
$parameters = array_reverse($parameters);
return str_replace(array_keys($parameters), array_map(fn($e) => is_numeric($e) ? $e : (
is_bool($e) ? (int) $e : $this->quote($e)
), array_values($parameters)), $sql);
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace Ulmus\Pdo;
trait SqlPdoTrait
{
protected int $openedTransaction = 0;
public function beginTransaction(): bool
{
if ( 0 === $this->openedTransaction++ ) {
return $this->openTransaction();
}
return $this->exec("SAVEPOINT transaction_{$this->openedTransaction}") !== false;
}
public function commit() : bool
{
if ( 0 === --$this->openedTransaction) {
return parent::commit();
}
return $this->exec("RELEASE SAVEPOINT transaction_{$this->openedTransaction}") !== false;
}
public function rollback() : bool
{
if ($this->openedTransaction > 1) {
return $this->exec('ROLLBACK TO transaction_' . $this->openedTransaction--) !== false;
}
elseif ($this->openedTransaction-- === 1) {
return parent::rollback();
}
return false;
}
protected function openTransaction() : bool
{
return parent::beginTransaction();
}
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace Ulmus\Pdo;
class Sqlite extends \PDO\Sqlite
{
use PdoTrait, SqlitePdoTrait;
}
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace Ulmus\Pdo;
trait SqlitePdoTrait
{
use SqlPdoTrait;
public bool $inTransaction = false;
public function inTransaction(): bool
{
return $this->openedTransaction > 0;
}
public function commit(): bool
{
if ( 0 === --$this->openedTransaction) {
return $this->exec("COMMIT") !== false;
}
return $this->exec("RELEASE SAVEPOINT transaction_{$this->openedTransaction}") !== false;
}
public function rollback() : bool
{
if ($this->openedTransaction > 1) {
return $this->exec('ROLLBACK TO transaction_' . $this->openedTransaction--) !== false;
}
elseif ($this->openedTransaction-- === 1) {
# We must do it manually since opening a transaction manually stucks PDO into thinking we've got no transaction opened
return $this->exec('ROLLBACK') !== false;
}
return false;
}
protected function openTransaction(): bool
{
return $this->exec("BEGIN IMMEDIATE TRANSACTION") !== false;
}
}