{"id":26675538,"url":"https://github.com/sakibweb/phdb","last_synced_at":"2026-04-09T08:09:21.738Z","repository":{"id":236927046,"uuid":"793439191","full_name":"sakibweb/PHDB","owner":"sakibweb","description":"PHDB is PHP Database Management Library","archived":false,"fork":false,"pushed_at":"2025-04-28T17:57:08.000Z","size":141,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-28T18:43:49.637Z","etag":null,"topics":["database","database-management","mariadb","mysql","sakibweb"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sakibweb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-29T08:21:20.000Z","updated_at":"2025-04-28T17:57:12.000Z","dependencies_parsed_at":"2024-04-29T09:37:27.991Z","dependency_job_id":"aa5a684f-fcac-4840-bf27-73479662b8ac","html_url":"https://github.com/sakibweb/PHDB","commit_stats":null,"previous_names":["sakibweb/phdb"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sakibweb/PHDB","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sakibweb%2FPHDB","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sakibweb%2FPHDB/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sakibweb%2FPHDB/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sakibweb%2FPHDB/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sakibweb","download_url":"https://codeload.github.com/sakibweb/PHDB/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sakibweb%2FPHDB/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267278631,"owners_count":24063252,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","database-management","mariadb","mysql","sakibweb"],"created_at":"2025-03-26T03:18:37.642Z","updated_at":"2026-04-09T08:09:21.679Z","avatar_url":"https://github.com/sakibweb.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PHDB - PHP Database Management Library\n\n**PHDB** is a lightweight PHP library designed to simplify common database interactions using the MySQLi extension. It provides a straightforward, static class interface for connecting to a MySQL database, performing CRUD (Create, Read, Update, Delete) operations, managing tables, executing raw queries, handling transactions, and more, with built-in error handling and basic SQL injection protection mechanisms.\n\n## Key Features\n\n*   **Connection Management:** Easily connect to and disconnect from your MySQL database using static configuration.\n*   **Error Handling:** Configurable error handling modes (die on error, return false, custom message) with access to the last error message.\n*   **Security Basics:**\n    *   Basic checks against common SQL injection patterns in raw queries.\n    *   Automatic escaping and backtick quoting of table/column identifiers.\n    *   Strong recommendation and support for **prepared statements** via the `query()` method for optimal security.\n*   **CRUD Operations:** Simplified methods for `insert()`, `update()`, `delete()`, and flexible `select()` queries.\n*   **Advanced Querying:**\n    *   Execute raw SQL with prepared statements (`query()`).\n    *   Fetch specific result sets (`specificSelect()`).\n    *   Retrieve single scalar values (`getValue()`, `getSpecificValue()`).\n    *   Search across multiple columns (`search()`).\n    *   Find records by specific criteria (`findBy()`).\n*   **Data Aggregation:** Calculate `count()`, `sum()`, `avg()`, `max()`, and `min()` directly.\n*   **Table Management:** Methods to `createTable()`, `dropTable()`, `alterTable()`, `truncateTable()`, and `addDB()`.\n*   **Schema Introspection:** Get table column names (`columns()`).\n*   **Batch Operations:** Efficiently insert multiple records (`batchInsert()`).\n*   **Transactions:** Execute multiple operations atomically using `transaction()`.\n*   **Utility Functions:**\n    *   Paginate query results easily (`paginate()`).\n    *   Clean database tables by removing duplicates or based on conditions (`clean()`).\n    *   Simplified insert/update logic (`save()`).\n\n## Installation\n\nPHDB is designed to be simple. No package manager is required.\n\n1.  Download the `PHDB.php` file.\n2.  Include it in your PHP project:\n\n```php\n\u003c?php\nrequire_once 'PHDB.php';\n?\u003e\n```\n\n## Usage\n\n### Configuration\n\nBefore using any database methods, configure your database connection details using the static properties. This typically happens once in your application's bootstrap or configuration file.\n\n```php\n\u003c?php\nrequire_once 'PHDB.php';\n\n// Database Credentials\nPHDB::$host = \"localhost\";         // Or your DB host IP/domain\nPHDB::$username = \"your_db_user\";\nPHDB::$password = \"your_db_password\";\nPHDB::$dbname = \"your_database_name\";\n\n// Optional: Set Character Set (Defaults to utf8mb4)\n// PHDB::$charset = 'utf8';\n\n// Optional: Customize Error Handling (Defaults to true)\n// PHDB::$error = true;  // Default: Prints error and dies (Good for development)\n// PHDB::$error = false; // Disables direct output, methods return false/specific error structure on failure. Use PHDB::error() to get the message. (Good for production)\n// PHDB::$error = \"Oops! A database error occurred.\"; // Shows a custom message and dies.\n?\u003e\n```\n\n### Connecting and Disconnecting\n\nConnection is usually handled automatically when you call a database method. However, you can explicitly connect or disconnect.\n\n```php\n// Explicitly connect (optional, done automatically by most methods if needed)\nPHDB::connect();\n\n// ... perform database operations ...\n\n// Explicitly disconnect (optional, done automatically after most queries unless in a transaction)\n// Note: Will not disconnect if a transaction is active.\n$disconnected = PHDB::disconnect();\n\n// Explicitly close the connection (alternative to disconnect, forces closure even if auto-disconnect failed)\nPHDB::close();\n```\n\n### Executing Raw Queries (`query()`)\n\nUse `query()` for executing any SQL statement, especially useful for complex queries or operations not covered by helper methods. **Use parameterized queries to prevent SQL injection.**\n\n**Return Values:**\n*   **SELECT, SHOW, DESCRIBE:** Returns an array of associative arrays representing the rows, or `false` on failure.\n*   **INSERT, UPDATE, DELETE, CREATE, ALTER, DROP:** Returns `true` on success, `false` on failure.\n*   **On Potential Injection / Error:** Returns `false` or an array `['status' =\u003e false, 'message' =\u003e '...']` if `PHDB::$error` is not `true`.\n\n```php\n// SELECT using Prepared Statement (Recommended for Security)\n$userId = 1;\n$status = 'active';\n$results = PHDB::query(\"SELECT id, name FROM users WHERE id = ? AND status = ?\", [$userId, $status]);\n\nif ($results === false) {\n    echo \"Query failed: \" . PHDB::error();\n} elseif (empty($results)) {\n    echo \"No users found.\";\n} else {\n    echo \"Users Found:\u003cbr\u003e\";\n    foreach ($results as $row) {\n        echo \"ID: \" . $row['id'] . \", Name: \" . $row['name'] . \"\u003cbr\u003e\";\n        // Output: e.g., ID: 1, Name: John Doe\n    }\n}\n\n// UPDATE using Prepared Statement\n$newStatus = 'inactive';\n$userIdToUpdate = 5;\n$success = PHDB::query(\"UPDATE users SET status = ? WHERE id = ?\", [$newStatus, $userIdToUpdate]);\n\nif ($success) {\n    echo \"User updated successfully.\";\n} else {\n    echo \"Update failed: \" . PHDB::error();\n}\n\n// CREATE TABLE (DDL)\n$success = PHDB::query(\"CREATE TABLE IF NOT EXISTS logs (id INT AUTO_INCREMENT PRIMARY KEY, message TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)\");\nif ($success) {\n    echo \"Table 'logs' created or already exists.\";\n} else {\n    echo \"Failed to create table: \" . PHDB::error();\n}\n```\n\n### Selecting Data (`select()`)\n\nA flexible method to build `SELECT` queries.\n\n**Return Value:** An array of associative arrays, or `false` on failure.\n\n```php\n// Select all columns from 'users'\n$allUsers = PHDB::select('users');\n\n// Select specific columns with a WHERE clause\n$activeUsers = PHDB::select('users', 'id, email', ['status' =\u003e 'active']);\n\n// Select with WHERE, ORDER BY, LIMIT, and OFFSET\n$usersPage2 = PHDB::select(\n    'users',                    // Table\n    'name, signup_date',        // Columns\n    ['status' =\u003e 'active'],     // Where conditions\n    10,                         // Limit\n    10,                         // Offset (10 * (page 2 - 1))\n    'signup_date DESC'          // Order By\n);\n\n// Select with a JOIN\n$joins = [\n    \"INNER JOIN profiles ON users.id = profiles.user_id\"\n];\n$usersWithProfiles = PHDB::select(\n    'users',                                    // Main table\n    'users.id, users.name, profiles.avatar',    // Columns (specify table for clarity)\n    ['users.status' =\u003e 'active'],               // Where\n    null, null, null, null,                     // Limit, Offset, OrderBy, GroupBy\n    $joins                                      // Joins array\n);\n\nif ($usersWithProfiles) {\n    foreach ($usersWithProfiles as $user) {\n        echo $user['name'] . ' - Avatar: ' . $user['avatar'] . '\u003cbr\u003e';\n    }\n}\n\n// Select distinct cities\n$distinctCities = PHDB::select('users', 'city', [], null, null, null, null, null, true); // Last arg true for DISTINCT\n```\n\n### Specific Select (`specificSelect()`)\n\nSimilar to `query()` but specifically intended for `SELECT` statements, often used when `select()` doesn't fit the query structure easily. Uses prepared statements.\n\n**Return Value:** An array of associative arrays, or `false` on failure.\n\n```php\n$minAge = 18;\n$query = \"SELECT name, email FROM users WHERE age \u003e ? ORDER BY name ASC\";\n$results = PHDB::specificSelect($query, [$minAge]);\n\nif ($results) {\n    foreach ($results as $row) {\n        echo $row['name'] . \" (\" . $row['email'] . \")\u003cbr\u003e\";\n    }\n}\n```\n\n### Getting Single Values\n\n#### `getValue()`\n\nRetrieves the value of a single column from the first matching row.\n\n**Return Value:** The specific value (mixed type) or `null` if not found or on error.\n\n```php\n$userId = 10;\n$username = PHDB::getValue('users', 'name', ['id' =\u003e $userId]);\n\nif ($username !== null) {\n    echo \"Username for ID $userId is: \" . $username; // e.g., Username for ID 10 is: JaneDoe\n} else {\n    echo \"User not found or error occurred.\";\n}\n```\n\n#### `getSpecificValue()`\n\nRetrieves a single scalar value using a custom query. Useful for aggregation results like COUNT, MAX etc., when you only need the single computed value.\n\n**Return Value:** The specific value (mixed type) or `null` if not found or on error.\n\n```php\n$totalUsers = PHDB::getSpecificValue(\"SELECT COUNT(*) FROM users\");\necho \"Total users: \" . ($totalUsers ?? 0); // e.g., Total users: 150\n\n$maxPrice = PHDB::getSpecificValue(\"SELECT MAX(price) FROM products WHERE category = ?\", ['electronics']);\necho \"Max electronics price: \" . ($maxPrice ?? 'N/A'); // e.g., Max electronics price: 1999.99\n```\n\n### Inserting Data\n\n#### `insert()`\n\nInserts a single record. Uses `ON DUPLICATE KEY UPDATE` implicitly, meaning if a unique key constraint (like a `PRIMARY KEY` or `UNIQUE` index) is violated, it will update the existing row instead of throwing an error. The `$overwrite` parameter's behavior in the current code might be less predictable due to the `ON DUPLICATE KEY` clause always being present; relying on the implicit update is generally recommended.\n\n**Return Value:** `true` on successful insert/update, `false` on failure.\n\n```php\n$userData = [\n    'name' =\u003e 'Peter Jones',\n    'email' =\u003e 'peter.jones@example.com',\n    'status' =\u003e 'pending',\n    'signup_date' =\u003e date('Y-m-d H:i:s') // Use current timestamp\n];\n\n$success = PHDB::insert('users', $userData);\n\nif ($success) {\n    echo \"User 'Peter Jones' inserted or updated.\";\n} else {\n    echo \"Failed to insert/update user: \" . PHDB::error();\n}\n```\n\n#### `batchInsert()`\n\nInserts multiple records efficiently in a single query.\n\n**Return Value:** `true` on success, `false` on failure.\n\n```php\n$newUsers = [\n    ['name' =\u003e 'Alice', 'email' =\u003e 'alice@example.com', 'status' =\u003e 'active'],\n    ['name' =\u003e 'Bob', 'email' =\u003e 'bob@example.com', 'status' =\u003e 'active'],\n    ['name' =\u003e 'Charlie', 'email' =\u003e 'charlie@example.com', 'status' =\u003e 'pending']\n];\n\n// Insert new records, fail if duplicates exist based on unique keys\n$success = PHDB::batchInsert('users', $newUsers);\n\n// Insert records, update rows if unique keys conflict\n// $success = PHDB::batchInsert('users', $newUsers, true); // Set $overwrite to true\n\nif ($success) {\n    echo count($newUsers) . \" users processed successfully.\";\n} else {\n    echo \"Batch insert failed: \" . PHDB::error();\n}\n```\n\n#### `save()`\n\nA convenience method to insert or update a record based on the presence of specific key(s) in the data. Checks if a record exists based on `$uniqueKey` (or `$check` if provided) and performs an UPDATE if found, otherwise an INSERT.\n\n**Return Value:** `true` on success, `false` on failure.\n\n```php\n// Example: Saving application settings (assuming 'name' is a unique key)\n$settingData = [\n    'name' =\u003e 'website_url',\n    'value' =\u003e 'https://new.example.com',\n    'description' =\u003e 'The main URL for the site'\n];\n\n// Will insert if 'website_url' doesn't exist, or update it if it does.\n// It checks for existence based on the 'name' field because it's provided in $data.\n// If 'id' was the primary key and included, it would likely check based on 'id'.\n// Specify the key explicitly for clarity:\n$success = PHDB::save('settings', $settingData, null, 'name'); // Check based on 'name'\n\nif ($success) {\n    echo \"Setting 'website_url' saved successfully.\";\n} else {\n    echo \"Failed to save setting: \" . PHDB::error();\n}\n```\n\n### Updating Data (`update()`)\n\nUpdates existing records based on a `WHERE` clause.\n\n**Return Value:** `true` on success (even if no rows were affected), `false` on failure.\n\n```php\n// Update status for a specific user\n$userId = 15;\n$updateData = ['status' =\u003e 'verified', 'last_login' =\u003e date('Y-m-d H:i:s')];\n$success = PHDB::update('users', $updateData, ['id' =\u003e $userId]);\n\nif ($success) {\n    echo \"User ID $userId updated.\";\n} else {\n    echo \"Failed to update user: \" . PHDB::error();\n}\n\n// Update multiple users\n$success = PHDB::update('users', ['status' =\u003e 'archived'], ['signup_date' \u003c '2023-01-01']);\n// Note: The above condition `signup_date \u003c '...'` won't work directly with the current\n// implementation which only supports `=` comparisons with prepared statements.\n// For complex WHERE clauses, use `query()`:\n$dateThreshold = '2023-01-01';\n$success = PHDB::query(\"UPDATE users SET status = ? WHERE signup_date \u003c ?\", ['archived', $dateThreshold]);\n\n```\n\n### Deleting Data\n\n#### `delete()` / `deleteBy()`\n\nDeletes records matching the `WHERE` conditions. `deleteBy()` is an alias for `delete()`.\n\n**Return Value:** `true` on success (even if no rows were affected), `false` on failure.\n\n```php\n// Delete a specific user by ID\n$userIdToDelete = 25;\n$success = PHDB::delete('users', ['id' =\u003e $userIdToDelete]);\n// $success = PHDB::deleteBy('users', ['id' =\u003e $userIdToDelete]); // Alias\n\nif ($success) {\n    echo \"Attempted to delete user ID $userIdToDelete.\";\n} else {\n    echo \"Failed to delete user: \" . PHDB::error();\n}\n\n// Delete all inactive users\n$success = PHDB::delete('users', ['status' =\u003e 'inactive']);\n\n// Delete ALL records from a table (use truncateTable for efficiency if needed)\n// $success = PHDB::delete('logs'); // Deletes all rows\n```\n\n### Table Management\n\n#### `createTable()`\n\nCreates a new table if it doesn't exist.\n\n**Return Value:** `true` on success, `false` on failure.\n\n```php\n$columns = [\n    'id' =\u003e 'INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY',\n    'product_name' =\u003e 'VARCHAR(255) NOT NULL',\n    'sku' =\u003e 'VARCHAR(100) UNIQUE',\n    'price' =\u003e 'DECIMAL(10, 2) DEFAULT 0.00',\n    'created_at' =\u003e 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP'\n];\n\n$success = PHDB::createTable('products', $columns);\n\nif ($success) {\n    echo \"Table 'products' created or already exists.\";\n} else {\n    echo \"Failed to create table 'products': \" . PHDB::error();\n}\n```\n\n#### `dropTable()`\n\nDrops an existing table. **Use with caution!**\n\n**Return Value:** `true` on success, `false` on failure.\n\n```php\n// $success = PHDB::dropTable('old_logs');\n// if ($success) {\n//     echo \"Table 'old_logs' dropped.\";\n// } else {\n//     echo \"Failed to drop table 'old_logs': \" . PHDB::error();\n// }\n```\n\n#### `alterTable()`\n\nModifies an existing table structure.\n\n**Return Value:** `true` on success, `false` on failure.\n\n```php\n$changes = [\n    'ADD COLUMN category VARCHAR(100) AFTER product_name',\n    'MODIFY COLUMN price DECIMAL(12, 2) DEFAULT 0.00',\n    'ADD INDEX idx_category (category)'\n];\n\n$success = PHDB::alterTable('products', $changes);\n\nif ($success) {\n    echo \"Table 'products' altered successfully.\";\n} else {\n    echo \"Failed to alter table 'products': \" . PHDB::error();\n}\n```\n\n#### `truncateTable()`\n\nRemoves all data from a table quickly. Resets AUTO_INCREMENT counter. **Use with caution!**\n\n**Return Value:** `true` on success, `false` on failure.\n\n```php\n// $success = PHDB::truncateTable('temporary_data');\n// if ($success) {\n//     echo \"Table 'temporary_data' truncated.\";\n// } else {\n//     echo \"Failed to truncate table: \" . PHDB::error();\n// }\n```\n\n#### `addDB()`\n\nCreates a new database if it doesn't exist. Requires appropriate database server privileges.\n\n**Return Value:** `true` on success, `false` on failure.\n\n```php\n// $success = PHDB::addDB('my_new_app_db');\n// if ($success) {\n//     echo \"Database 'my_new_app_db' created or already exists.\";\n// } else {\n//     echo \"Failed to create database: \" . PHDB::error();\n// }\n```\n\n### Schema Introspection (`columns()`)\n\nRetrieves a list of column names for a given table.\n\n**Return Value:** An array of column name strings, or an empty array on failure.\n\n```php\n$userColumns = PHDB::columns('users');\necho \"Columns in 'users' table: \" . implode(', ', $userColumns);\n// Output: e.g., Columns in 'users' table: id, name, email, status, signup_date, last_login\n\n// Get columns containing 'date'\n$dateColumns = PHDB::columns('users', 'date');\necho \"Date-related columns: \" . implode(', ', $dateColumns);\n// Output: e.g., Date-related columns: signup_date\n\n// Get columns *except* primary key ('id') and timestamps\n$dataColumns = PHDB::columns('users', null, ['id', 'created_at', 'updated_at']);\necho \"Main data columns: \" . implode(', ', $dataColumns);\n// Output: e.g., Main data columns: name, email, status, signup_date, last_login\n```\n\n### Finding and Searching\n\n#### `findBy()`\n\nAn alias for `select()` often used semantically for finding records based on specific criteria.\n\n**Return Value:** An array of associative arrays, or `false` on failure.\n\n```php\n$pendingUsers = PHDB::findBy('users', '*', ['status' =\u003e 'pending']); // Same as select('users', '*', ['status' =\u003e 'pending'])\n\nif ($pendingUsers) {\n    echo count($pendingUsers) . \" pending users found.\";\n}\n```\n\n#### `search()`\n\nPerforms a `LIKE` search. Can search specific columns (if `$conditions` is an array) or *all* table columns (if `$conditions` is a string).\n\n**Return Value:** An array of associative arrays, or `false` on failure.\n\n```php\n// Search for users where name LIKE '%john%' AND email LIKE '%example.com%'\n$searchResults = PHDB::search('users', 'id, name', ['name' =\u003e 'john', 'email' =\u003e 'example.com']);\n\n// Search for users where *any* column contains the word 'admin'\n$keyword = 'admin';\n$adminRelatedUsers = PHDB::search('users', '*', $keyword);\n\nif ($adminRelatedUsers) {\n    echo \"Found \" . count($adminRelatedUsers) . \" records matching '$keyword' in any column.\u003cbr\u003e\";\n    foreach ($adminRelatedUsers as $user) {\n        // process results\n    }\n}\n```\n\n### Aggregation Functions\n\nThese functions compute aggregate values directly.\n\n**Return Value:** Numeric value (int/float) or `null` (for MIN/MAX if no rows match), or 0 (for SUM/AVG/COUNT if no rows match).\n\n```php\n// Count total users\n$totalUsers = PHDB::count('users');\necho \"Total Users: $totalUsers\u003cbr\u003e\"; // e.g., Total Users: 150\n\n// Count active users\n$activeCount = PHDB::count('users', ['status' =\u003e 'active']);\necho \"Active Users: $activeCount\u003cbr\u003e\"; // e.g., Active Users: 125\n\n// Sum of prices for electronics\n$totalElecValue = PHDB::sum('products', 'price', ['category' =\u003e 'electronics']);\necho \"Total Electronics Value: $\" . number_format($totalElecValue, 2) . \"\u003cbr\u003e\"; // e.g., Total Electronics Value: $25430.50\n\n// Average price of all products\n$avgPrice = PHDB::avg('products', 'price');\necho \"Average Product Price: $\" . number_format($avgPrice, 2) . \"\u003cbr\u003e\"; // e.g., Average Product Price: $45.99\n\n// Highest price\n$maxPrice = PHDB::max('products', 'price');\necho \"Maximum Price: $\" . number_format($maxPrice ?? 0, 2) . \"\u003cbr\u003e\"; // e.g., Maximum Price: $1999.99\n\n// Lowest price for 'books'\n$minBookPrice = PHDB::min('products', 'price', ['category' =\u003e 'books']);\necho \"Minimum Book Price: $\" . number_format($minBookPrice ?? 0, 2) . \"\u003cbr\u003e\"; // e.g., Minimum Book Price: $9.95\n```\n\n### Pagination (`paginate()`)\n\nRetrieves a slice of data suitable for pagination, along with metadata.\n\n**Return Value:** An array containing pagination info and data, or `false` on failure.\n*   `data`: Array of associative arrays for the current page.\n*   `total`: Total number of records matching the criteria.\n*   `per_page`: Records per page requested.\n*   `current_page`: The current page number.\n*   `last_page`: The total number of pages.\n*   `from`: The record number of the first item on the current page.\n*   `to`: The record number of the last item on the current page.\n\n```php\n$currentPage = $_GET['page'] ?? 1; // Get current page from request, default to 1\n$perPage = 15;\n\n$paginationResult = PHDB::paginate(\n    'products',                 // Table\n    'id, product_name, price',  // Columns\n    ['status' =\u003e 'available'],  // Where condition (optional)\n    $currentPage,               // Current page number\n    $perPage                    // Items per page\n);\n\nif ($paginationResult === false) {\n    echo \"Failed to retrieve products: \" . PHDB::error();\n} elseif ($paginationResult['total'] \u003e 0) {\n    echo \"\u003ch2\u003eProducts (Page \" . $paginationResult['current_page'] . \" of \" . $paginationResult['last_page'] . \")\u003c/h2\u003e\";\n    echo \"\u003cp\u003eShowing records \" . $paginationResult['from'] . \" to \" . $paginationResult['to'] . \" of \" . $paginationResult['total'] . \" total.\u003c/p\u003e\";\n\n    echo \"\u003cul\u003e\";\n    foreach ($paginationResult['data'] as $product) {\n        echo \"\u003cli\u003e\" . $product['product_name'] . \" - $\" . $product['price'] . \"\u003c/li\u003e\";\n    }\n    echo \"\u003c/ul\u003e\";\n\n    // Add pagination links (logic not shown, use the returned variables)\n    // Example: if ($paginationResult['current_page'] \u003c $paginationResult['last_page']) { echo \"\u003ca href='?page=\".($currentPage+1).\"'\u003eNext\u003c/a\u003e\"; }\n\n} else {\n    echo \"No products found.\";\n}\n```\n\n### Transactions (`transaction()`)\n\nExecute a series of database operations atomically. If any operation fails within the callback (returns `false` or throws an Exception), all changes are rolled back. Otherwise, all changes are committed.\n\n**Return Value:** `true` if the transaction committed successfully, `false` if it rolled back.\n\n```php\n$userId = 5;\n$orderAmount = 100.50;\n$productId = 101;\n$quantity = 2;\n\n$success = PHDB::transaction(function() use ($userId, $orderAmount, $productId, $quantity) {\n\n    // 1. Create the order\n    $orderData = ['user_id' =\u003e $userId, 'total_amount' =\u003e $orderAmount, 'order_date' =\u003e date('Y-m-d H:i:s')];\n    if (!PHDB::insert('orders', $orderData)) {\n        return false; // Rollback on failure\n    }\n\n    // Assuming insert doesn't easily return the ID here, let's get it (simplistic example)\n    $lastOrderId = PHDB::getSpecificValue(\"SELECT LAST_INSERT_ID()\");\n    if (!$lastOrderId) return false; // Rollback\n\n    // 2. Add order item\n    $itemData = ['order_id' =\u003e $lastOrderId, 'product_id' =\u003e $productId, 'quantity' =\u003e $quantity];\n    if (!PHDB::insert('order_items', $itemData)) {\n        return false; // Rollback on failure\n    }\n\n    // 3. Decrease stock (Example - requires stock table)\n    $stockUpdate = PHDB::query(\n        \"UPDATE product_stock SET quantity = quantity - ? WHERE product_id = ? AND quantity \u003e= ?\",\n        [$quantity, $productId, $quantity]\n    );\n    // Check if update succeeded AND affected a row (meaning stock was sufficient)\n    if (!$stockUpdate || PHDB::$conn-\u003eaffected_rows === 0) { // Access internal conn property *within transaction*\n        PHDB::handleError(\"Insufficient stock for product ID $productId\", true); // Log error, continue to rollback\n        return false; // Rollback\n    }\n\n    // If all steps succeeded\n    return true; // Commit\n});\n\nif ($success) {\n    echo \"Order placed successfully!\";\n} else {\n    echo \"Order failed. Transaction rolled back. Error: \" . PHDB::error();\n}\n```\n\n### Cleaning Data (`clean()`)\n\nProvides various options to clean up data in a table, such as removing duplicate rows or rows with empty values. **Use with extreme caution, especially on production data. Backup is highly recommended.**\n\n**Return Value:** An array containing cleaning statistics, or `false` on failure.\n*   `total_before`: Row count before cleaning.\n*   `total_after`: Row count after cleaning.\n*   `duplicates_removed`: Rows removed due to duplication rules.\n*   `empty_removed`: Rows removed due to empty column rules.\n*   `value_removed`: Rows removed due to specific value conditions.\n*   `backup_created`: Boolean indicating if backup was successful.\n*   `backup_table`: Name of the backup table created (if `backup` was true).\n\n```php\n// Example: Clean the 'temp_imports' table\n// - Create a backup table first\n// - Remove rows that are complete duplicates across all columns\n// - Remove rows where 'email' or 'product_sku' is empty or null\n\n$options = [\n    'backup' =\u003e true, // Create a backup table (e.g., temp_imports_backup_YYYYMMDD_HHMMSS)\n    // 'backup_table' =\u003e 'my_custom_backup_name', // Optional: Specify custom backup name\n    'duplicate_all' =\u003e true, // Remove rows where all column values match another row\n    'empty_cols' =\u003e ['email', 'product_sku'], // Remove if 'email' OR 'product_sku' is empty/null\n    // 'duplicate_cols' =\u003e ['email'], // Alternative: Remove rows with duplicate emails, keeping one\n    // 'value_conditions' =\u003e ['status' =\u003e 'error'], // Remove rows where status is 'error'\n    'min_rows' =\u003e 1 // Keep at least one row when removing duplicates based on columns\n];\n\n$cleanResult = PHDB::clean('temp_imports', $options);\n\nif ($cleanResult === false) {\n    echo \"Table cleaning failed: \" . PHDB::error();\n} else {\n    echo \"\u003ch2\u003eCleaning Results for 'temp_imports':\u003c/h2\u003e\";\n    echo \"Backup Created: \" . ($cleanResult['backup_created'] ? 'Yes (' . $cleanResult['backup_table'] . ')' : 'No') . \"\u003cbr\u003e\";\n    echo \"Rows Before: \" . $cleanResult['total_before'] . \"\u003cbr\u003e\";\n    echo \"Duplicate Rows Removed: \" . $cleanResult['duplicates_removed'] . \"\u003cbr\u003e\";\n    echo \"Empty Value Rows Removed: \" . $cleanResult['empty_removed'] . \"\u003cbr\u003e\";\n    echo \"Value Condition Rows Removed: \" . $cleanResult['value_removed'] . \"\u003cbr\u003e\";\n    echo \"Rows After: \" . $cleanResult['total_after'] . \"\u003cbr\u003e\";\n}\n\n```\n\n## Error Handling\n\nThe `PHDB::$error` static property controls how errors are handled:\n\n*   **`true` (Default):** When a database error occurs, the error message is printed directly to the output (and logged via `error_log`), and the script execution stops (`die()`). This is useful during development and debugging.\n*   **`false`:** Errors are suppressed from direct output. Methods that encounter an error will return `false` (or a specific error structure like `['status' =\u003e false, 'message' =\u003e '...']` for `query` injection check). You should check the return value of PHDB methods and can retrieve the last error message using `PHDB::error()`. This mode gives you more control in production environments.\n*   **`'Custom Message'` (string):** If you set `$error` to a string, that custom message will be printed (and logged via `error_log`), and the script will stop (`die()`).\n\n### Handling Errors Gracefully (when `PHDB::$error = false;`)\n\n```php\n\u003c?php\nrequire_once 'PHDB.php';\n\n// Configure...\nPHDB::$host = \"localhost\";\nPHDB::$username = \"user\";\nPHDB::$password = \"pass\";\nPHDB::$dbname = \"test_db\";\n\n// Set error mode to return false on failure\nPHDB::$error = false;\n\n// Try a query that might fail (e.g., non-existent table)\n$result = PHDB::select('non_existent_table', '*');\n\nif ($result === false) {\n    // An error occurred\n    $errorMessage = PHDB::error(); // Get the actual MySQLi error message\n    error_log(\"Database Error: \" . $errorMessage); // Log the detailed error\n    echo \"Sorry, we couldn't retrieve the data at this time. Please try again later.\"; // Show user-friendly message\n    // Potentially redirect or display an error page\n} else {\n    // Query succeeded, process $result (which is an array of rows)\n    if (empty($result)) {\n        echo \"No data found.\";\n    } else {\n        print_r($result);\n    }\n}\n\n// Example checking query() return\n$updateSuccess = PHDB::query(\"UPDATE users SET name = ? WHERE id = ?\", [\"Test\", 9999]);\nif ($updateSuccess === false) {\n    $errorMessage = PHDB::error();\n    error_log(\"Update Failed: \" . $errorMessage);\n    // handle failure...\n}\n?\u003e\n```\n\n## Security Considerations\n\n*   **SQL Injection:** PHDB provides basic protection by checking raw queries passed to `query()` against a list of common malicious patterns (`isPotentiallyMalicious()`). However, **this is not foolproof**.\n*   **Prepared Statements:** **The most effective way to prevent SQL injection is to use prepared statements.** Use the `query()` method with `?` placeholders and the `$params` array whenever dealing with user-supplied input. Methods like `select()`, `insert()`, `update()`, `delete()`, `getValue()`, etc., *already use prepared statements internally* for their conditions and data, making them inherently safer for those specific operations.\n*   **Input Sanitization:** Always validate and sanitize user input *before* passing it to any PHDB method, especially if constructing parts of queries dynamically (which should be avoided if possible). Use functions like `filter_input()`, `filter_var()`, or custom validation logic.\n*   **Identifier Quoting:** The library automatically adds backticks (`` ` ``) around table and column names in most helper methods (`select`, `insert`, `update`, `delete`, etc.) to prevent issues with reserved keywords or special characters in identifiers.\n*   **Least Privilege:** Ensure the database user configured (`PHDB::$username`) has only the necessary permissions required for the application to function. Avoid using root or administrative accounts for regular application operations.\n\n## License\n\nThis project is licensed under the **MIT License**. See the LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsakibweb%2Fphdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsakibweb%2Fphdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsakibweb%2Fphdb/lists"}