Unlike the original, this class is no longer static but must be instantiated with a constructor.
The rows of records are no longer fetched directly by the functions, but must be fetched with the fetch() function or fetched all together with the fetchAll() function. The fetch() function saves memory by fetching records one by one instead of storing them in a table or an object.
All the functions have been renamed from UpperCamelCase to lowerCamelCase to comply with PSR12.
The connection settings are stored in phpformbuilder/database/db-connect.php as constants. This allows to connect using $db->connect() without any argument
The debugging system has been improved
Some additional functions have been added:
$db->error()
$db->fetch()
$db->fetchAll()
$db->getColumns()
$db->getColumnsNames()
$db->getTables()
$db->rowCount()
$db->selectCount()
$db->setDebugMode()
$db->getDebugContent()
The protected $db->whereClause($where) has been edited to accept fields prefixed with their table name (ie: [table.field => value]) in the $where argument.
A private function $db->interpolateQuery($qry, $params) has been added to show the raw SQL query string from PDO prepared statements when thye query fails and the error is displayed.
The documentation HTML has been rewrited.
Introduction
All of the code is in a single file to make it incredibly easy to install and learn.
It uses an internal global PDO database connection to make it easier to retrofit into existing projects or use in new projects.
I also made every effort to take care of all the details like:
Incredibly easy-to-use and detailed debugging
Automatic SQL generation
Try/catch error checking
Error event handling and PHP error logging
Security
Full transaction processing
and using as little memory and being as lightweight as possible while still containing a lot of great features.
Some basic knowledge of how PDO "placeholders" work is helpful but not necessary. Every effort to use them is applied to stop SQL injection hacks and also because:
"There is a common misconception about how the placeholders in prepared statements work. They are not simply substituted in as (escaped) strings, and the resulting SQL executed. Instead, a DBMS asked to "prepare" a statement comes up with a complete query plan for how it would execute that query, including which tables and indexes it would use."
Define the DBUSER, DBPASS, DBNAME and DBHOST constants in phpformbuilder/database/db-connect.php
Then require phpformbuilder/database/db-connect.php and you can connect to both your localhost and production server using $db = new DB(); without any argument.
Argument
Type
Description
$show_errors
Boolean
If false then the errors are registered and can be called using $db->error() but no errors are shown.
$username
String
Database user name. Default: DBUSER
$password
String
Database password Default: DBPASS
$database
String
Database or schema name Default: DBNAME
$hostname
String
Host name of the server Default: DBHOST
If there is an error connecting and $show_errors is set to true the error will be displayed on screen. If there is no error the function doesn't return anything.
// register the database connection settings
require_once 'phpformbuilder/database/db-connect.php';
// Include the database class
require_once 'phpformbuilder/database/DB.php';
// Then connect to the database
$db = new DB();
// or connect and show all the encountered errors automatically
$db = new DB(true);
// or connect, then test the connection and retrieve the error if the database is not connected
$db = new DB();
if (!$db->isConnected()) {
$error_message = $db->error();
}
execute
Executes a SQL statement using PDO.
If you have a SQL statement that needs to be executed and doesn't return anything (usually an INSERT, UPDATE, or DELETE), use this method. Use $db->insert, $db->update, or $db->delete if you are not using SQL (these methods automatically generate and execute SQL for you on the backend).
Associative array placeholders for binding to SQL. array('name' => 'Cathy', 'city' => 'Cape Cod')
$debug
Boolean
If set to true, will output results and query information. In debug mode the insert, update and delete requests are simulated, no change is made to your database.
The return result varies depending on the situation. If the SQL was an INSERT statement, the primary key of the record will be returned. Otherwise, if there was an error, false is returned. If the execution was sucessful, true is returned.
// Execute a SQL query and return whether it was successful or not
// (FYI: You can also use $db->safe() to return a safe quoted string for SQL)
$sql = "INSERT INTO productlines (id, name, description) VALUES (null, 'bikes', 'Lorem ipsum')";
$id = $db->execute($sql);
// Execute a SQL query with placeholders (better because it stops SQL Injection hacks)
$sql = 'DELETE FROM productlines WHERE name = :name AND description = :description';
$values = array('name' => 'bikes', 'description' => 'Lorem ipsum');
$success = $db->execute($sql, $values);
// Execute the same SQL statement but only in debug mode
// In debug mode, the record will not be saved
$success = $db->execute($sql, $values, true);
query
Executes a SQL statement using PDO
If you have a SQL statement that returns records (usually a SELECT), use this method. Use $db->select if you are not using or don't want to use SQL.
Associative array placeholders for binding to SQL. array('name' => 'David', 'city' => 'Dallas')
$debug
Boolean
If set to true, will output results and query information
returns true, or false if there is an error executing the SQL.
// Execute a SQL query to return an object containing all rows
$sql = "SELECT * FROM customers WHERE country = 'Indonesia'";
$db->query($sql);
// Execute the same query in debug mode
$db->query($sql, array(), true);
// Execute the same query using placeholders (better because it stops SQL Injection hacks)
$sql = "SELECT id, first_name, last_name FROM customers WHERE country = :country";
$values = array('country' => 'Indonesia');
$db->query($sql, $values);
// Execute the same query in debug mode
$db->query($sql, $values, true);
// loop through the results
while ($row = $db->fetch()) {
echo $row->first_name . ' ' . $row->last_name . '<br>';
}
// or fetch all the records then loop
// (this function should not be used if a huge number of rows have been selected, otherwise it will consume a lot of memory)
$rows = $db->fetchAll();
foreach($rows as $row) {
echo $row->first_name . ' ' . $row->last_name . '<br>';
}
queryRow
Executes a SQL statement using PDO and returns a single row as an object.
Executes a SQL statement using PDO exactly the same way $db->query does except only one row is returned. The syntax is identical. If more than more row would be returned by a given SQL query, using this method, only the first row would be returned. Don't forget to try setting debug mode to true.
Associative array placeholders for binding to SQL. array('name' => 'Emma', 'city' => 'Eureka')
$debug
Boolean
If set to true, will output results and query information
$fetch_parameters
Function parameter
PDO fetch style record options (i.e. \PDO::FETCH_OBJ, \PDO::FETCH_ASSOC, \PDO::FETCH_NUM, or \PDO::FETCH_BOTH)
If there is an error executing the SQL, false is returned. Otherwise, the data is returned in the format set by $fetch_parameters.
// Execute a SQL query with placeholders to return only one row
$sql = 'SELECT first_name, last_name FROM customers WHERE id = :id LIMIT 1';
$row = $db->queryRow($sql, array('id' => 5));
echo $row->first_name . ' - ' . $row->last_name;
queryValue
Executes a SQL statement using PDO and returns a single value.
Executes a SQL statement using PDO exactly the same way $db->query does except only one value is returned. This is excellent for getting a single value like a name or a primary key. If more than more row or column would be returned by a given SQL query, using this method, only the first value on the first row would be returned.
Associative array placeholders for binding to SQL. array('name' => 'Fred', 'city' => 'Fargo')
$debug
Boolean
If set to true, will output results and query information
If there is an error executing the SQL, false is returned. Otherwise, the data is returned as a single value.
// Execute a SQL query to return only one value
$sql = 'SELECT last_name FROM customers WHERE id = 1';
$value = $db->queryValue($sql);
// Show the value
echo $value;
select
Retrieves data from a specified table with the possible joins using PDO.
This is different from $db->query because it does not require any SQL. If you need records from a single table, use this method.
The table with the possible joins containing the records to be retrieved
$values
String|Array
The list of fields to be returned. This can be a string like "name" or "state, zipcode" or an array of columns like array('id', 'amount'). If not specified, all fields will be returned.
$where
String|Array
An array containing the fields and values like array("id" => 1, "active" => true) or array('id >' => 123, 'first_name IS NOT NULL'). This can also be a string containing a where clause without the beginning word WHERE like "id = 1 AND age > 18"
$extras
Array
An array containing the optional following pairs of key => values:
Key
Values
Default
'select_distinct'
If set to true the query will use SELECT DISTINCT instead of SELECT.
false
'order_by'
Array or string containing field order, or null to not specify any order. This can be a string like "name" or "state, zipcode" or an array of columns like array('id', 'amount')
null
'limit'
Integer or string containing the maximum number of results, or null to not specify any limit. E.g: 'limit' => 10 or 'limit' => '10, 20'
null
$debug
Boolean
If set to true, will output results and query information
returns true, or false if there is an error executing the SQL.
// Select rows without using SQL
$values = array('id', 'first_name', 'last_name');
$where = array('country' => 'Indonesia');
$db->select('customers', $values, $where);
// We can make more complex where clauses in the Select, Update, and Delete methods
$values = array('id', 'first_name', 'last_name');
$where = array(
'zip_code IS NOT NULL',
'id >' => 10,
'last_name LIKE' => '%Ge%'
);
$db->select('customers', $values, $where);
// Let's sort by descending ID and run it in debug mode
$extras = array('order_by' => 'id DESC');
$db->select('customers', $values, $where, $extras, true);
// loop through the results
while ($row = $db->fetch()) {
echo $row->first_name . ' ' . $row->last_name . '<br>';
}
// or fetch all the records then loop
// (this function should not be used if a huge number of rows have been selected, otherwise it will consume a lot of memory)
$rows = $db->fetchAll();
foreach($rows as $row) {
echo $row->first_name . ' ' . $row->last_name . '<br>';
}
selectCount
Count the number of records in a table, or the number of not-null values in one or several fields.
Retrieves data the same way $db->select does except only one row is returned. The syntax is nearly identical.
The table with the possible joins containing the record to be retrieved
$values
String|Array
Array of fieldnames => aliases to be returned. Default will count the number of records and return it with the rows_count alias. If you choose one or several fields it'll return the number of NOT NULL values for each one of them.
$where
String|Array
An array containing the fields and values like array("id" => 1, "active" => true) or array('id >' => 123, 'first_name IS NOT NULL'). This can also be a string containing a where clause without the beginning word WHERE like "id = 1 AND age > 18".
$debug
Boolean
If set to true, will output results and query information
If there is an error retrieving the records, false is returned. Otherwise, the data is returned as an associative array where the key is the alias of the field name.
// Count the number of records in the 'customers' table
$row = $db->selectCount('customers');
echo '
Customers count: ' . $row->rows_count . '
';
// Count the number of customers zip codes and states that are not null
$values = array(
'zip_code' => 'zip_code_count',
'state' => 'state_count'
);
$row = $db->selectCount('customers', $values);
echo '
' . $row->zip_code_count . ' customers zip codes are not null.
';
echo '
' . $row->state_count . ' customers states are not null.
';
selectRow
Retrieves data from a specified table with the possible joins using PDO and returns a single row as an array.
Retrieves data the same way $db->select does except only one row is returned. The syntax is nearly identical. If more than more row would be returned, using this method, only the first row would be returned.
This is different from $db->queryRow because it does not require any SQL. If you need a single row from a table, use this method.
The table with the possible joins containing the record to be retrieved
$where
String|Array
An array containing the fields and values like array("id" => 1, "active" => true) or array('id >' => 123, 'first_name IS NOT NULL'). This can also be a string containing a where clause without the beginning word WHERE like "id = 1 AND age > 18".
$debug
Boolean
If set to true, will output results and query information
$fetch_parameters
Function parameter
PDO fetch style record options (i.e. \PDO::FETCH_OBJ, \PDO::FETCH_ASSOC, \PDO::FETCH_NUM, or \PDO::FETCH_BOTH)
If there is an error retrieving the records, false is returned. Otherwise, the data is returned as an associative array where the key is the field name.
// If only one row is needed, use the selectRow method
$row = $db->selectRow('customers', '*', array('id' => 12));
// Show some of the values
echo $row->first_name . ' ' . $row->last_name;
selectValue
Retrieves data from a specified table with the possible joins using PDO and returns a single value.
Retrieves data the same way $db->select does except only one value is returned. This is excellent for getting a single value like a name or a primary key. If more than more row or column would be returned, using this method, only the first value on the first row would be returned.
This is different from $db->queryValue because it does not require any SQL. If you need a single value from the database, use this method.
The table with the possible joins containing the value to be retrieved
$field
String
The name of the field to be returned
$where
String|Array
An array containing the fields and values like array("id" => 1, "active" => true) or array('id >' => 123, 'first_name IS NOT NULL'). This can also be a string containing a where clause without the beginning word WHERE like "id = 1 AND age > 18".
$debug
Boolean
If set to true, will output results and query information
If there is an error retrieving the records, false is returned. Otherwise, the data is returned as an associative array where the key is the field name.
// Grab one value - get the email of the customer in the record with ID 32
$value = $db->selectValue('customers', 'email', array('id' => 32));
insert
Inserts a new record into a table using PDO.
This method will insert a row into a table. Behind the scenes, this method actually generates and executes a SQL INSERT statement returning the primary key of the new row. No SQL is required using this method.
$db->insert($table, $values, $debug = false)
Argument
Type
Description
$table*
String
The table where the data will be inserted into the database
$values
Array
The list of fields to be saved. This is an associative array of keys of the column names and their respective values like array('name' => 'Ted', 'amount' => 123.45)
$debug
Boolean
If set to true, will output results and query information. Any insert transaction flagged as debug will be rolled back and will not be saved
If there is an error inserting the record, false is returned. Otherwise, the primary key is returned for the new row.
// Insert a new record
$values = array('id' => null, 'customers_id' => 5, 'payment_date' => '2022-05-11', 'amount' => 2224.5);
$success = $db->insert('payments', $values);
// Show the last insert id
if ($success) {
echo 'Last insert id is: ' . $db->getLastInsertId();
}
// Try it in debug mode
// In debug mode, the record will not be saved
$success = $db->insert('payments', $values, true);
update
Updates an existing record into a table using PDO.
This method will update a row in a table. Behind the scenes, this method actually generates and executes a SQL UPDATE statement, but no SQL is required using this method.
The list of fields to be saved. This is an associative array of keys of the column names and their respective values like array('name' => 'Vick', 'customer' => true)
$where
String|Array
An array containing the fields and values like array("id" => 1, "active" => true) or array('id >' => 123, 'first_name IS NOT NULL'). This can also be a string containing a where clause without the beginning word WHERE like "id = 1 AND age > 18". If no where clause is specified, ALL records in the table will be updated.
$debug
Boolean
If set to true, will output results and query information. Any update transaction flagged as debug will be rolled back and will not be saved
If there is an error updating a record, false is returned. Otherwise, true is returned on success.
// Update an existing record
$update = array('amount' => 3565);
$where = array('customers_id' => 5, 'payment_date' => '2022-05-11');
$success = $db->update('payments', $update, $where);
// Try it in debug mode
// In debug mode, the record will not be updated
$success = $db->update('payments', $update, $where, true);
delete
Deletes a record from a table using PDO.
This method will delete a row in a table. Behind the scenes, this method actually generates and executes a SQL DELETE statement, but no SQL is required using this method.
An array containing the fields and values like array("id" => 1, "active" => true) or array('id >' => 123, 'first_name IS NOT NULL'). This can also be a string containing a where clause without the beginning word WHERE like "id = 1 AND age > 18". If no where clause is specified, ALL records in the table will be deleted.
$debug
Boolean
If set to true, will output results and query information. Any delete transaction flagged as debug will be rolled back and the records will not be deleted
If there is an error deleting a record, false is returned. Otherwise, true is returned on success.
// Delete records
$where = array('active' => false);
$where = array('customers_id' => 5, 'payment_date' => '2022-05-11');
$success = $db->delete('payments', $where);
// Try it in debug mode
// In debug mode, the record will not be deleted
$success = $db->delete('payments', $where, true);
fetch
Fetches the next row from a result set and returns it according to the $fetch_parameters format.
Call this method to loop through the PDO statements
$db->fetch($fetch_parameters = \PDO::FETCH_OBJ)
Argument
Type
Description
$fetch_parameters
Function parameter
PDO fetch style record options (i.e. \PDO::FETCH_OBJ, \PDO::FETCH_ASSOC, \PDO::FETCH_NUM, or \PDO::FETCH_BOTH)
Returns the next row from a result set
// Select rows first
$values = array('id', 'first_name', 'last_name');
$where = array('country' => 'Indonesia');
$db->select('customers', $values, $where);
// loop through the results
while ($row = $db->fetch()) {
echo $row->name . '<br>';
}
// or retrive an array instead of an object
while ($row = $db->fetch(\PDO::FETCH_ASSOC)) {
echo $row['name'] . '<br>';
}
fetchAll
Fetches all rows from a result set and return them according to the $fetch_parameters format.
Call this method to retrieve all the records into a single object and/or array
PDO fetch style record options (i.e. \PDO::FETCH_OBJ, \PDO::FETCH_ASSOC, \PDO::FETCH_NUM, or \PDO::FETCH_BOTH)
Returns the all the rows from a result set
// Select rows first
$values = array('id', 'first_name', 'last_name');
$where = array('country' => 'Indonesia');
$db->select('customers', $values, $where);
// fetch all the records then loop
// (this function should not be used if a huge number of rows have been selected, otherwise it will consume a lot of memory)
$rows = $db->fetchAll();
foreach($rows as $row) {
echo $row->name . '<br>';
}
// or retrieve an array instead of an object
$rows = $db->fetchAll(\PDO::FETCH_ASSOC);
foreach($rows as $row) {
echo $row['name'] . '<br>';
}
getColumns
Gets the information about the columns in a given table
Call this method to retrieve information about the columns in a given table.
Call this method to retrieve all the tables of the database into an array
$db->getTables()
Returns the all the tables from the active database, or false if no table is found.
// Retrieve the tables from the database into an array
$tables = $db->getTables();
if (!$tables) {
echo 'No table found.';
} else {
echo '
';
// loop the tables
foreach ($tables as $table) {
echo $table . ' ';
}
echo '
';
}
Transaction Processing
Allows for full transaction processing using PDO.
Transaction processing is used to maintain database integrity by ensuring that batches of MySQL operations execute completely or not at all.
Transaction processing is a mechanism used to manage sets of MySQL operations that must be executed in batches to ensure that databases never contain the results of partial operations. With transaction processing, you can ensure that sets of operations are not aborted mid-processing they either execute in their entirety or not at all (unless explicitly instructed otherwise). If no error occurs, the entire set of statements is committed (written) to the database tables. If an error does occur, a rollback (undo) can occur to restore the database to a known and safe state.
The key to managing transactions involves breaking your SQL statements into logical chunks and explicitly stating when data should be rolled back and when it should not.
NOTE: When using transaction processing, debugging mode will not rollback any inserts, updates, or deletes. You have to call the $db->transactionRollback(); function by yourself.
If there is an error, false is returned. Otherwise, true is returned on success.
Example 1 - single request
// Begin a transaction
$db->transactionBegin();
try {
// Perform any action on the database here
// such as insert, update, and delete
$success = $db->insert($table, $values);
// If success, commit and save the transaction
if ($success) {
$db->transactionCommit();
}
} catch (Exception $e) {
// If there was a problem, rollback the transaction
// as if no database actions here had ever happened
$db->transactionRollback();
// Show the error if the DB class don't show it by itself
if (!$db->show_errors) {
echo $e->getMessage();
}
}
Example 2 - multiple conditional requests
// Begin a transaction
$db->transactionBegin();
try {
if ($db->insert($table, $values)) {
if ($db->delete($table, $where)) {
// If success, commit and save the entire transaction
$db->transactionCommit();
}
}
} catch (Exception $e) {
// If there was a problem, rollback the transaction
// as if no database actions here had ever happened
$db->transactionRollback();
// Show the error if the DB class doesn't show it by itself
if (!$db->show_errors) {
echo $e->getMessage();
}
}
Example 3 - multiple conditional requests with negative logic
// Begin a transaction
$db->transactionBegin();
try {
if (!$db->insert($table, $values)) {
throw new \Exception($db->error());
}
// continue if no error has been thrown before
if (!$db->insert($table_2, $values_2)) {
throw new \Exception($db->error());
}
// commit and save the entire transaction
// only if no error has been thrown before
$db->transactionCommit();
} catch (\Exception $e) {
// If there was a problem, rollback the transaction
// as if no database actions here had ever happened
$db->transactionRollback();
// Show the error if the DB class doesn't show it by itself
if (!$db->show_errors) {
echo $e->getMessage();
}
}
convertQueryToSimpleArray
Converts the array results from a Query() or Select() into a simple array using only one column or an associative array using another column as a key.
This method is useful for converting a query into a key => value pair.
Returns the last encountered error, or an empty string if no error.
$db->error()
// Create a new DB object with $show_errors turned off
$db = new DB();
// make some requests, then show the errors when you want to
echo $db->error();
getLastInsertId
Returns the id of the last inserted record.
$db->getLastInsertId()
This method returns the id of the last record inserted by an INSERT query.
$id = $db->getLastInsertId();
isConnected
Returns the status of the database connection (true/false).
$db->isConnected()
Example of use:
if (!$db->isConnected()) {
// the connection failed ...
echo $db->error();
} else {
// we are connected...
}
rowCount
Returns the number of results of the last SQL SELECT statement.
$db->rowCount()
This method returns the number of records returned by a SELECT query.
$db_count = $db->rowCount();
safe
Returns a quoted string using PDO that is safe to pass into an SQL statement.
This support function internally uses $db->quote() to place quotes around an input string (if required) and escapes special characters within the input string, using a quoting style appropriate to the underlying driver.
If you are using this function to build SQL statements, you are strongly recommended to use placeholders instead. Prepared statements with bound parameters are not only more portable, more convenient, immune to SQL injection, but are often much faster to execute than interpolated queries, as both the server and client side can cache a compiled form of the query.
Not all PDO drivers implement this method (notably PDO_ODBC).
$db->safe($value)
$values = array('name' => $db->safe($name));
errorEvent
This is an event function located at the top of the DB.php file that is called every time there is an error.
If $show_errors is set to true all the errors will be displayed on screen with the error number, code and details.
You can add code into this function (or override it when inheriting this class) to do things such as:
Log errors into the database
Send an email with the error message
Save out to some type of log file
Make a RESTful API call
Run a script or program
Set a session or global variable
Or anything you might want to do when an error occurs
protected function errorEvent($error, $error_code = 0)
Argument
Type
Description
$error*
String
The error message
$error_code
String
An error code
This method does not return any value.
MultipleDatabases
Using Multiple Databases
You can create as many different connections as you need by setting the connection informations when you instanciate the $db object.
// Connect to the database 1
$db1 = new DB('user_local', 'pass_local', 'development', 'localhost');
// Connect to the database 2
$db2 = new DB('appuser', 'pass123', 'production', 'my_server');
Debugging with the DB class
The DB class allows you to activate debugging at two different levels:
The $show_errors argument of the __construct function
The $debug argument of the requests functions
The $show_errors argument of the __construct function
If you activate it, all the encountered errors will be displayed on screen (connection failure, unsuccessful requests, ...).
The $debug argument
All the request functions have a $debug argument.
This argument enables full debugging of the performance, queries and arguments used by the PDO object.
Depending on the debugging mode being used, the results will either be displayed on screen or registered in the $db object.
You can choose the debugging mode using the setDebugMode($debug_mode) function
You can get the debug content using the getDebugContent() function
setDebugMode
Sets the active debugging mode
$db->setDebugMode($debug_mode)
Argument
Type
Description
$debug_mode*
String
The debugging mode to enable. 'echo' or 'register'
If 'echo' the debugging information will be displayed directly on the screen on each database request.
If 'register' the debugging information is registered internally and can then be retrieved using the getDebugContent() function
getDebugContent
Returns the registered debugging information when the debug mode has been set to 'register'.
$db->getDebugContent($mode = 'html')
Argument
Type
Description
$mode*
String
The mode to retrieve the debug output. 'html' or 'json'
The 'json' mode returns a JSON encoded string with the HTML debug content inside. Useful especially to get the content with Javascript and Ajax.