File manager - Edit - /home/webapp69.cm.in.th/u69319090028/Shop/app/Helpers/DB.php
Back
<?php /** * Database Helper * Handles Transaction Wrapping, Row Locking, and Atomic Concurrency Operations */ require_once __DIR__ . '/../../database/Database.php'; class DB { private static int $transactionDepth = 0; /** * Execute a callback within an atomic Database Transaction * Automatically commits on success, rolls back on any exception/error */ public static function transaction(callable $callback) { $pdo = Database::getInstance(); if (self::$transactionDepth === 0) { $pdo->beginTransaction(); } else { $pdo->exec("SAVEPOINT TRANS_SP_" . self::$transactionDepth); } self::$transactionDepth++; try { $result = $callback($pdo); self::$transactionDepth--; if (self::$transactionDepth === 0) { $pdo->commit(); } else { $pdo->exec("RELEASE SAVEPOINT TRANS_SP_" . (self::$transactionDepth + 1)); } return $result; } catch (Throwable $e) { self::$transactionDepth--; if (self::$transactionDepth === 0) { if ($pdo->inTransaction()) { $pdo->rollBack(); } } else { $pdo->exec("ROLLBACK TO SAVEPOINT TRANS_SP_" . (self::$transactionDepth + 1)); } throw $e; } } /** * Execute a query with Row-Level Lock for Concurrency Protection */ public static function selectForUpdate(string $sql, array $params = []): array { $pdo = Database::getInstance(); // Append FOR UPDATE if not present if (stripos($sql, 'FOR UPDATE') === false) { $sql .= ' FOR UPDATE'; } $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt->fetchAll() ?: []; } /** * Single Row Lock */ public static function lockRow(string $table, int $id, string $primaryKey = 'id'): ?array { $pdo = Database::getInstance(); $sql = "SELECT * FROM `{$table}` WHERE `{$primaryKey}` = :id FOR UPDATE"; $stmt = $pdo->prepare($sql); $stmt->execute([':id' => $id]); $row = $stmt->fetch(); return $row ?: null; } /** * Atomic safe decrement (e.g. Stock decrement with stock >= qty protection) * Returns true if decremented, false if condition failed (e.g. out of stock) */ public static function atomicDecrement(string $table, string $column, float $amount, string $where, array $params = [], bool $preventNegative = true): bool { $pdo = Database::getInstance(); $condition = $where; if ($preventNegative) { $condition .= " AND `{$column}` >= :_min_sub_amt"; $params[':_min_sub_amt'] = $amount; } $sql = "UPDATE `{$table}` SET `{$column}` = `{$column}` - :_sub_amt WHERE {$condition}"; $params[':_sub_amt'] = $amount; $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt->rowCount() > 0; } /** * Atomic safe increment */ public static function atomicIncrement(string $table, string $column, float $amount, string $where, array $params = []): bool { $pdo = Database::getInstance(); $sql = "UPDATE `{$table}` SET `{$column}` = `{$column}` + :_add_amt WHERE {$where}"; $params[':_add_amt'] = $amount; $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt->rowCount() > 0; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.23 |
proxy
|
phpinfo
|
Settings