I have this DB class that extends PDO, that also has useful functions for certain tasks; I was wondering how well it's coded, and if so, what I could maybe improve on. I tried commenting in PHPDoc to explain each functions usage, but if any are confusing, don't hesitate to let me know so I can try and explain it a bit better.
I am really just looking for advice on where I can improve, and if not already, how to make the class more OOP.
<?php
/**
* Connect into a specified database
*
* Connect into a database using/extending PDO. Must set
* HOST, USER, & PASS credentials in order for it to properly
* work.
*
* @param string $DB_NAME database name to connect into.
*/
class DB extends PDO{
public object $connect;
public bool $connected;
public string $latest_error_message;
private const HOST = "hostname";
private const USER = "username";
private const PASS = "password";
public function __construct(string $DB_NAME){
try{
$this->connect = new \PDO("mysql:host=".self::HOST.";dbname=".$DB_NAME, self::USER, self::PASS);
$this->connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connected = true;
}catch(PDOException $e){
$this->connected = false;
$this->latest_error_message = $e->getMessage();
}
}
/**
* Inserts an array into the specified table as a row using column=>value pairs
*
* Using key=>value pairs as column=>value pairs, insert each value of the
* array into its coresponding column based on the key name.
*
* (e.g.) If you have a table called "data", with 2 columns inside named "id" & "name",
* and want to add a row with the values "567" & "Crimin4L" respectively; you can execute
* the following:
*
* DB::insert_row( "data", ["id"=>"567", "name"=>"Crimin4L"] );
*
* @param string $table table name
* @param array $column_value_pairs associative arrays with key=>value pairs as column=>value pairs
* @return bool
* @throws PDOException
*/
public function insert_row(string $table, array $column_value_pairs){
try{
$qhalf1 = "INSERT INTO `${table}` (";
$qhalf2 = ") VALUES (";
foreach($column_value_pairs as $column => $v): $qhalf1 .= "${column}, "; $qhalf2 .= ":${column}, "; endforeach;
$query = substr($qhalf1, 0, strlen($qhalf1) - 2).substr($qhalf2, 0, strlen($qhalf2) - 2).")";
$prep = $this->connect->prepare($query);
foreach($column_value_pairs as $column => $value){
if(is_string($value)) $prep->bindValue(":${column}", $value, PDO::PARAM_STR);
elseif(is_int($value)) $prep->bindValue(":${column}", $value, PDO::PARAM_INT);
elseif(is_bool($value)) $prep->bindValue(":${column}", $value, PDO::PARAM_BOOL);
}
$prep->execute();
if($prep->rowCount() > 0) return true;
else return false;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Executes a quick query for backend purposes (Unsecure)
*
* @param string $query
* @return object|bool
* @throws PDOException
*/
public function exec_query(string $query){
try{
$qstart = $this->connect->prepare($query);
$qstart->execute();
return $qstart;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Check if the specified table exists
*
* @param string $table
* @return bool
* @throws PDOException
*/
public function is_table(string $table){
try{
$qstart = $this->connect->prepare("DESCRIBE `${table}`");
if($qstart->execute()) return true;
else return false;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Drop/Delete specified table(s)
*
* @param string|array $table
* @return bool|array
* @throws PDOException
*/
public function drop_table(string|array $table){
try{
if(is_string($table)){
$qstart = $this->connect->prepare("DROP TABLE `${table}`");
if($qstart->execute()) return true;
else return false;
}elseif(is_array($table)){
$r = [];
foreach($table as $t){
$qstart = $this->connect->prepare("DROP TABLE `${t}`");
if($qstart->execute()) $r[] = true;
else $r[] = false;
}
return $r;
}else return false;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Truncate a specified table(s)
*
* @param string|array $table
* @return bool|array
* @throws PDOException
*/
public function truncate_table(array|string $table){
try{
if(is_string($table)){
$qstart = $this->connect->prepare("TRUNCATE TABLE `${table}`");
if($qstart->execute()) return true;
else return false;
}elseif(is_array($table)){
$r = [];
foreach($table as $t){
$qstart = $this->connect->prepare("TRUNCATE TABLE `${t}`");
if($qstart->execute()) $r[] = true;
else $r[] = false;
}
return $r;
}else return false;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Shuffle a specified table
*
* @param string $table
* @return bool
* @throws PDOException
*/
public function shuffle_table(string $table){
try{
$query = $this->exec_query("SELECT * FROM `${table}`");
if($table_data = $query->fetchAll(PDO::FETCH_ASSOC)){
$table_data_shuffled = $this->shuffle_assoc($table_data);
if($this->truncate_table($table)){
foreach($table_data_shuffled as $data) $this->insert_row($table, $data);
return true;
}else return false;
}else return false;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Delete row(s) based on search column and/or search parameters.
*
* @param string $table table to delete from
* @param string|bool $searchColumn column name to search from (or false if $searchParameter is an associative array)
* @param string|int|bool|array $searchParameter value(s) to search for; if multiple values, use an indexed array;
* if multiple columns & values, use associative array as column=>value pairs and mark $searchColumn false
* @return bool|array
* @throws PDOException
*/
public function delete_row(string $table, string|bool $searchColumn, string|int|bool|array $searchParameter){
try{
if(is_string($searchColumn) && is_array($searchParameter)){
$r = [];
foreach($searchParameter as $sP){
$delQuery = $this->connect->prepare("DELETE FROM `${table}` WHERE ${searchColumn}=:${searchColumn} LIMIT 1");
if(is_string($sP)) $delQuery->bindValue(":${searchColumn}", $sP, PDO::PARAM_STR);
elseif(is_int($sP)) $delQuery->bindValue(":${searchColumn}", $sP, PDO::PARAM_INT);
elseif(is_bool($sP)) $delQuery->bindValue(":${searchColumn}", $sP, PDO::PARAM_BOOL);
if($delQuery->execute()) $r[] = true;
else $r[] = true;
}
return $r;
}elseif($searchColumn == false && is_array($searchParameter)){
$r = [];
foreach($searchParameter as $sC => $sP){
$delQuery = $this->connect->prepare("DELETE FROM `${table}` WHERE ${sC}=:${sC} LIMIT 1");
if(is_string($sP)) $delQuery->bindValue(":${sC}", $sP, PDO::PARAM_STR);
elseif(is_int($sP)) $delQuery->bindValue(":${sC}", $sP, PDO::PARAM_INT);
elseif(is_bool($sP)) $delQuery->bindValue(":${sC}", $sP, PDO::PARAM_BOOL);
if($delQuery->execute()) $r[] = true;
else $r[] = true;
}
return $r;
}elseif(is_string($searchColumn) && !is_array($searchParameter)){
$delQuery = $this->connect->prepare("DELETE FROM `${table}` WHERE ${searchColumn}=:${searchColumn} LIMIT 1");
if(is_string($searchParameter)) $delQuery->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_STR);
elseif(is_int($searchParameter)) $delQuery->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_INT);
elseif(is_bool($searchParameter)) $delQuery->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_BOOL);
if($delQuery->execute()) return true;
else return false;
}else return false;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Select specified row
*
* Find a row(s) based on specified column & parameters
*
* @param string $table
* @param string $searchColumn
* @param string|int|bool $searchParameter
* @param int $limit
* @return object
* @throws PDOException
*/
public function select_row(string $table, string $searchColumn, string|int|bool $searchParameter, int $limit = 1){
try{
$query = $this->connect->prepare("SELECT * FROM `${table}` WHERE ${searchColumn}=:${searchColumn} LIMIT ${limit}");
if(is_string($searchParameter)) $query->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_STR);
elseif(is_int($searchParameter)) $query->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_INT);
elseif(is_bool($searchParameter)) $query->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_BOOL);
if($query->execute()) return $query;
else return false;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Fetch an associative array from a table
*
* Fetch an associative array from a table of a row(s)
* based on the search column and parameter provided.
*
* @param string $table
* @param string $searchColumn
* @param string|int|bool $searchParameter
* @param int $limit
* @return array|bool
* @throws PDOException
*/
public function fetch_assoc_row(string $table, string $searchColumn, string|int|bool $searchParameter, int $limit = 1){
try{
$query = $this->connect->prepare("SELECT * FROM `${table}` WHERE ${searchColumn}=:${searchColumn} LIMIT ${limit}");
if(is_string($searchParameter)) $query->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_STR);
elseif(is_int($searchParameter)) $query->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_INT);
elseif(is_bool($searchParameter)) $query->bindValue(":${searchColumn}", $searchParameter, PDO::PARAM_BOOL);
if($query->execute()) return $query->fetch(PDO::FETCH_ASSOC);
else return false;
}catch(PDOException $e){
$this->latest_error_message = $e->getMessage();
return false;
}
}
/**
* Shuffle an associative array
*
* @param array $array
* @return array
* @throws PDOException
*/
public static function shuffle_assoc(array $array){
$keys = array_keys($array);
shuffle($keys);
foreach($keys as $k) $r[$k] = $array[$k];
return $r;
}
}