- Working on revamping Ulmus bases classes
This commit is contained in:
1 parent
c417b00ed4
commit
25ab845886
12 files changed
+303
-52
No files matched your search
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Ulmus\Pdo;
|
||||
|
||||
class Mssql extends \PDO
|
||||
{
|
||||
use PdoTrait;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Ulmus\Pdo;
|
||||
|
||||
class Mysql extends \PDO\Mysql
|
||||
{
|
||||
use PdoTrait;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Ulmus\Pdo;
|
||||
|
||||
class Sqlite extends \PDO\Sqlite
|
||||
{
|
||||
use PdoTrait, SqlitePdoTrait;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user