# Database Module A static wrapper around WordPress's `$wpdb` global that provides a unified interface with consistent error handling. **Namespace:** `Reservair\Database` ## Why Direct `$wpdb` usage has two problems: error handling is manual (check `$wpdb->last_error` after every call) and the API is inconsistent (`insert` returns `false|int`, `get_results` returns `null|array`, etc.). `Db` normalises this — all failures throw `DbException`, all collection methods return `array`, and `insert` returns the new row's ID directly. The namespace also prevents conflicts with any other plugin that might define a `Db` class in the global scope. ## Usage ```php use Reservair\Database\Db; use Reservair\Database\DbException; // SELECT — single row $row = Db::get_row('SELECT * FROM %i WHERE id = %d', [$table, $id], ARRAY_A); // SELECT — multiple rows $rows = Db::get_results('SELECT * FROM %i WHERE status = %s', [$table, 'active']); // SELECT — scalar value $count = Db::get_var('SELECT COUNT(*) FROM %i', [$table]); // SELECT — single column $ids = Db::get_col('SELECT id FROM %i WHERE active = 1', [$table]); // INSERT — returns new row ID $id = Db::insert(Db::prefix() . 'rsv_reservations', ['name' => 'Alice', 'seats' => 2]); // UPDATE — returns number of rows affected $affected = Db::update(Db::prefix() . 'rsv_reservations', ['seats' => 3], ['id' => $id]); // DELETE — returns number of rows deleted $deleted = Db::delete(Db::prefix() . 'rsv_reservations', ['id' => $id]); // Raw query (DDL, transactions, etc.) Db::query('ALTER TABLE %i ADD COLUMN notes TEXT', [$table]); // Transactions try { Db::begin_transaction(); Db::insert(...); Db::update(...); Db::commit(); } catch (DbException $e) { Db::rollback(); throw $e; } // Helpers $prefix = Db::prefix(); // e.g. "wp_" $lastId = Db::last_insert_id(); $charsetCollate = Db::charset_collate(); // e.g. "DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" ``` ## Error handling Every method throws `DbException` (extends `\RuntimeException`) on failure. You do not need to check `$wpdb->last_error` manually. ```php use Reservair\Database\Db; use Reservair\Database\DbException; try { Db::insert(Db::prefix() . 'rsv_reservations', $data); } catch (DbException $e) { // $e->getMessage() contains the $wpdb error string } ``` ## API reference | Method | Returns | Notes | |---|---|---| | `Db::query(sql, params)` | `int` — rows affected | Use for DDL and raw DML | | `Db::get_row(sql, params, output)` | `object\|array\|null` | `null` = no match | | `Db::get_results(sql, params, output)` | `array` | Empty array when no rows | | `Db::get_var(sql, params)` | `?string` | `null` = no match | | `Db::get_col(sql, params)` | `array` | Empty array when no rows | | `Db::insert(table, data, format)` | `int` — new row ID | | | `Db::update(table, data, where, format, where_format)` | `int` — rows affected | | | `Db::delete(table, where, where_format)` | `int` — rows deleted | | | `Db::begin_transaction()` | `void` | | | `Db::commit()` | `void` | | | `Db::rollback()` | `void` | | | `Db::prefix()` | `string` | e.g. `"wp_"` | | `Db::last_insert_id()` | `int` | | | `Db::charset_collate()` | `string` | Use in `CREATE TABLE` DDL | All `sql` parameters are passed through `$wpdb->prepare()` when `params` is non-empty.