Add: DatabaseService class for abstracted database operations
- Created DatabaseService.php with full OOP database abstraction layer - Methods: select(), selectOne(), insert(), update(), delete(), execute(), count(), exists() - Transaction support: beginTransaction(), commit(), rollback() - Error handling: getLastError(), getLastQuery() for debugging - Type-safe parameter binding with prepared statements - Updated connection.php to initialize $db service - Available globally as $db variable after connection.php include - Foundation for migrating from procedural $conn queries
This commit is contained in:
320
classes/DatabaseService.php
Normal file
320
classes/DatabaseService.php
Normal file
@@ -0,0 +1,320 @@
|
||||
<?php
|
||||
/**
|
||||
* DatabaseService Class
|
||||
*
|
||||
* Provides a centralized database abstraction layer for all database operations.
|
||||
* Enforces prepared statements, proper error handling, and type safety.
|
||||
*
|
||||
* @package 4WDCSA
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
class DatabaseService {
|
||||
private $conn;
|
||||
private $lastError = null;
|
||||
private $lastQuery = null;
|
||||
|
||||
/**
|
||||
* Constructor - Initialize database connection
|
||||
*
|
||||
* @param mysqli $connection The MySQLi connection object
|
||||
*/
|
||||
public function __construct($connection) {
|
||||
if (!$connection) {
|
||||
throw new Exception("Database connection failed");
|
||||
}
|
||||
$this->conn = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last error message
|
||||
*
|
||||
* @return string|null The last error or null if no error
|
||||
*/
|
||||
public function getLastError() {
|
||||
return $this->lastError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last executed query
|
||||
*
|
||||
* @return string|null The last query or null
|
||||
*/
|
||||
public function getLastQuery() {
|
||||
return $this->lastQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a SELECT query with parameter binding
|
||||
*
|
||||
* @param string $query SQL query with ? placeholders
|
||||
* @param array $params Parameters to bind
|
||||
* @param string $types Type specification string (e.g., "isi" for int, string, int)
|
||||
* @return array|false Array of results or false on error
|
||||
*/
|
||||
public function select($query, $params = [], $types = "") {
|
||||
try {
|
||||
$this->lastQuery = $query;
|
||||
$stmt = $this->conn->prepare($query);
|
||||
|
||||
if (!$stmt) {
|
||||
$this->lastError = "Prepare failed: " . $this->conn->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($params) && !empty($types)) {
|
||||
if (!$stmt->bind_param($types, ...$params)) {
|
||||
$this->lastError = "Bind failed: " . $stmt->error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
$this->lastError = "Execute failed: " . $stmt->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$data = [];
|
||||
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$data[] = $row;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
return $data;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$this->lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a SELECT query returning a single row
|
||||
*
|
||||
* @param string $query SQL query with ? placeholders
|
||||
* @param array $params Parameters to bind
|
||||
* @param string $types Type specification string
|
||||
* @return array|false Single row as associative array or false
|
||||
*/
|
||||
public function selectOne($query, $params = [], $types = "") {
|
||||
$results = $this->select($query, $params, $types);
|
||||
return ($results && count($results) > 0) ? $results[0] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an INSERT query
|
||||
*
|
||||
* @param string $query SQL query with ? placeholders
|
||||
* @param array $params Parameters to bind
|
||||
* @param string $types Type specification string
|
||||
* @return int|false Last insert ID or false on error
|
||||
*/
|
||||
public function insert($query, $params = [], $types = "") {
|
||||
try {
|
||||
$this->lastQuery = $query;
|
||||
$stmt = $this->conn->prepare($query);
|
||||
|
||||
if (!$stmt) {
|
||||
$this->lastError = "Prepare failed: " . $this->conn->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($params) && !empty($types)) {
|
||||
if (!$stmt->bind_param($types, ...$params)) {
|
||||
$this->lastError = "Bind failed: " . $stmt->error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
$this->lastError = "Execute failed: " . $stmt->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
$insertId = $stmt->insert_id;
|
||||
$stmt->close();
|
||||
return $insertId;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$this->lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an UPDATE query
|
||||
*
|
||||
* @param string $query SQL query with ? placeholders
|
||||
* @param array $params Parameters to bind
|
||||
* @param string $types Type specification string
|
||||
* @return int|false Number of affected rows or false on error
|
||||
*/
|
||||
public function update($query, $params = [], $types = "") {
|
||||
try {
|
||||
$this->lastQuery = $query;
|
||||
$stmt = $this->conn->prepare($query);
|
||||
|
||||
if (!$stmt) {
|
||||
$this->lastError = "Prepare failed: " . $this->conn->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($params) && !empty($types)) {
|
||||
if (!$stmt->bind_param($types, ...$params)) {
|
||||
$this->lastError = "Bind failed: " . $stmt->error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
$this->lastError = "Execute failed: " . $stmt->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
$affectedRows = $stmt->affected_rows;
|
||||
$stmt->close();
|
||||
return $affectedRows;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$this->lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a DELETE query
|
||||
*
|
||||
* @param string $query SQL query with ? placeholders
|
||||
* @param array $params Parameters to bind
|
||||
* @param string $types Type specification string
|
||||
* @return int|false Number of affected rows or false on error
|
||||
*/
|
||||
public function delete($query, $params = [], $types = "") {
|
||||
return $this->update($query, $params, $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an arbitrary query (for complex queries)
|
||||
*
|
||||
* @param string $query SQL query with ? placeholders
|
||||
* @param array $params Parameters to bind
|
||||
* @param string $types Type specification string
|
||||
* @return mixed Query result or false on error
|
||||
*/
|
||||
public function execute($query, $params = [], $types = "") {
|
||||
try {
|
||||
$this->lastQuery = $query;
|
||||
$stmt = $this->conn->prepare($query);
|
||||
|
||||
if (!$stmt) {
|
||||
$this->lastError = "Prepare failed: " . $this->conn->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($params) && !empty($types)) {
|
||||
if (!$stmt->bind_param($types, ...$params)) {
|
||||
$this->lastError = "Bind failed: " . $stmt->error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
$this->lastError = "Execute failed: " . $stmt->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$this->lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count rows matching a condition
|
||||
*
|
||||
* @param string $table Table name
|
||||
* @param string $where WHERE clause (without WHERE keyword)
|
||||
* @param array $params Parameters to bind
|
||||
* @param string $types Type specification string
|
||||
* @return int|false Row count or false on error
|
||||
*/
|
||||
public function count($table, $where = "1=1", $params = [], $types = "") {
|
||||
$query = "SELECT COUNT(*) as count FROM {$table} WHERE {$where}";
|
||||
$result = $this->selectOne($query, $params, $types);
|
||||
return ($result) ? (int)$result['count'] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a record exists
|
||||
*
|
||||
* @param string $table Table name
|
||||
* @param string $where WHERE clause (without WHERE keyword)
|
||||
* @param array $params Parameters to bind
|
||||
* @param string $types Type specification string
|
||||
* @return bool True if record exists, false otherwise
|
||||
*/
|
||||
public function exists($table, $where, $params = [], $types = "") {
|
||||
$count = $this->count($table, $where, $params, $types);
|
||||
return ($count !== false && $count > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MySQLi connection object for advanced operations
|
||||
*
|
||||
* @return mysqli The MySQLi connection
|
||||
*/
|
||||
public function getConnection() {
|
||||
return $this->conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a transaction
|
||||
*
|
||||
* @return bool Success status
|
||||
*/
|
||||
public function beginTransaction() {
|
||||
try {
|
||||
$this->conn->begin_transaction();
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
$this->lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit a transaction
|
||||
*
|
||||
* @return bool Success status
|
||||
*/
|
||||
public function commit() {
|
||||
try {
|
||||
$this->conn->commit();
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
$this->lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback a transaction
|
||||
*
|
||||
* @return bool Success status
|
||||
*/
|
||||
public function rollback() {
|
||||
try {
|
||||
$this->conn->rollback();
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
$this->lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -13,3 +13,7 @@ if(!$conn = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname)){
|
||||
}
|
||||
|
||||
date_default_timezone_set('Africa/Johannesburg');
|
||||
|
||||
// Initialize DatabaseService for modern queries
|
||||
require_once(__DIR__ . '/classes/DatabaseService.php');
|
||||
$db = new DatabaseService($conn);
|
||||
|
||||
Reference in New Issue
Block a user