feat: return mysqli_result from executor methods

This commit is contained in:
Victor Westerlund 2024-01-08 13:03:48 +01:00
parent 3f97e7b1f0
commit f31d396c00
3 changed files with 34 additions and 63 deletions

View file

@ -8,7 +8,7 @@ $db->for(string $table)
->with(array $model) ->with(array $model)
->where(array $filters) ->where(array $filters)
->order(array $order_by) ->order(array $order_by)
->limit(1) ->limit(int|array $limit)
->select(array $columns): array|bool; ->select(array $columns): array|bool;
``` ```
which would be equivalent to the following in MySQL: which would be equivalent to the following in MySQL:

View file

@ -1,44 +0,0 @@
<?php
namespace libmysqldriver\Driver;
use \mysqli;
use \mysqli_stmt;
use \mysqli_result;
// MySQL query builder and executer abstractions
class DatabaseDriver extends mysqli {
// Passing arguments to https://www.php.net/manual/en/mysqli.construct.php
function __construct() {
parent::__construct(...func_get_args());
}
// Coerce input to single dimensional array
private static function to_list_array(mixed $input): array {
return array_values(is_array($input) ? $input : [$input]);
}
// Execute SQL query with optional prepared statement and return array of affected rows
public function exec(string $sql, mixed $params = null): array {
$query = $this->execute_query($sql, self::to_list_array($params));
$res = [];
// Fetch rows into sequential array
while ($row = $query->fetch_assoc()) {
$res[] = $row;
}
return $res;
}
// Execute SQL query with optional prepared statement and return true if query was successful
public function exec_bool(string $sql, mixed $params = null): bool {
$query = $this->execute_query($sql, self::to_list_array($params));
return gettype($query) === "boolean"
// Type is already a bool, so return it as is
? $query
// Return true if rows were matched
: $query->num_rows > 0;
}
}

View file

@ -3,14 +3,13 @@
namespace libmysqldriver; namespace libmysqldriver;
use \Exception; use \Exception;
use \victorwesterlund\xEnum;
use libmysqldriver\Driver\DatabaseDriver; use \mysqli;
use \mysqli_stmt;
require_once "DatabaseDriver.php"; use \mysqli_result;
// Interface for MySQL_Driver with abstractions for data manipulation // Interface for MySQL_Driver with abstractions for data manipulation
class MySQL extends DatabaseDriver { class MySQL extends mysqli {
private string $table; private string $table;
private ?array $model = null; private ?array $model = null;
@ -25,12 +24,21 @@
parent::__construct(...func_get_args()); parent::__construct(...func_get_args());
} }
/*
# Helper methods
*/
private function throw_if_no_table() { private function throw_if_no_table() {
if (!$this->table) { if (!$this->table) {
throw new Exception("No table name defined"); throw new Exception("No table name defined");
} }
} }
// Coerce input to single dimensional array
private static function to_list_array(mixed $input): array {
return array_values(is_array($input) ? $input : [$input]);
}
// Return value(s) that exist in $this->model // Return value(s) that exist in $this->model
private function in_model(string|array $columns): ?array { private function in_model(string|array $columns): ?array {
// Place string into array // Place string into array
@ -39,7 +47,11 @@
return array_filter($columns, fn($col): string => in_array($col, $this->model)); return array_filter($columns, fn($col): string => in_array($col, $this->model));
} }
/* ---- */ /*
# Definers
These methods are used to build an SQL query by chaining methods together.
Defined parameters will then be executed by an Executer method.
*/
// Use the following table name // Use the following table name
public function for(string $table): self { public function for(string $table): self {
@ -155,10 +167,13 @@
return $this; return $this;
} }
/* ---- */ /*
# Executors
These methods execute various statements that each return a mysqli_result
*/
// Create Prepared Statament for SELECT with optional WHERE filters // Create Prepared Statament for SELECT with optional WHERE filters
public function select(array|string|null $columns = null): array|bool { public function select(array|string|null $columns = null): mysqli_result {
$this->throw_if_no_table(); $this->throw_if_no_table();
// Create array of columns from CSV // Create array of columns from CSV
@ -184,19 +199,14 @@
// Interpolate components into an SQL SELECT statmenet and execute // Interpolate components into an SQL SELECT statmenet and execute
$sql = "SELECT {$columns_sql} FROM {$this->table}{$filter_sql}{$order_by_sql}{$limit_sql}"; $sql = "SELECT {$columns_sql} FROM {$this->table}{$filter_sql}{$order_by_sql}{$limit_sql}";
// No columns were specified, return true if query matched rows
if (!$columns) {
return $this->exec_bool($sql, $this->filter_values);
}
// Return array of matched rows // Return array of matched rows
$exec = $this->exec($sql, $this->filter_values); $exec = $this->execute_query($sql, self::to_list_array($this->filter_values));
// Return array if exec was successful. Return as flattened array if flag is set // Return array if exec was successful. Return as flattened array if flag is set
return empty($exec) || !$this->flatten ? $exec : $exec[0]; return empty($exec) || !$this->flatten ? $exec : $exec[0];
} }
// Create Prepared Statement for UPDATE using PRIMARY KEY as anchor // Create Prepared Statement for UPDATE using PRIMARY KEY as anchor
public function update(array $entity): bool { public function update(array $entity): mysqli_result {
$this->throw_if_no_table(); $this->throw_if_no_table();
// Make constraint for table model if defined // Make constraint for table model if defined
@ -224,11 +234,11 @@
// Interpolate components into an SQL UPDATE statement and execute // Interpolate components into an SQL UPDATE statement and execute
$sql = "UPDATE {$this->table} SET {$changes} {$filter_sql}"; $sql = "UPDATE {$this->table} SET {$changes} {$filter_sql}";
return $this->exec_bool($sql, $values); return $this->execute_query($sql, self::to_list_array($values));
} }
// Create Prepared Statemt for INSERT // Create Prepared Statemt for INSERT
public function insert(array $values): bool { public function insert(array $values): mysqli_result {
$this->throw_if_no_table(); $this->throw_if_no_table();
// A value for each column in table model must be provided // A value for each column in table model must be provided
@ -241,6 +251,11 @@
// Interpolate components into an SQL INSERT statement and execute // Interpolate components into an SQL INSERT statement and execute
$sql = "INSERT INTO {$this->table} VALUES ({$values_stmt})"; $sql = "INSERT INTO {$this->table} VALUES ({$values_stmt})";
return $this->exec_bool($sql, $values); return $this->execute_query($sql, self::to_list_array($values));
}
// Execute SQL query with optional prepared statement and return mysqli_result
public function exec(string $sql, mixed $params = null): mysqli_result {
return $this->execute_query($sql, self::to_list_array($params));
} }
} }