Docs: DatabaseService usage examples and migration guide
- Added comprehensive before/after examples - Covers: SELECT, SELECT one, INSERT, UPDATE, DELETE, COUNT, EXISTS - Transaction handling examples - Type specification reference (i, d, s, b) - Migration path and benefits summary - Reduces query code by 50-75% - Guide for gradual implementation throughout codebase
This commit is contained in:
368
DATABASE_SERVICE_EXAMPLES.md
Normal file
368
DATABASE_SERVICE_EXAMPLES.md
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
# DatabaseService Usage Examples
|
||||||
|
|
||||||
|
This document shows how to refactor existing code to use the new `DatabaseService` class for cleaner, more maintainable database operations.
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
Files are using the procedural MySQLi pattern:
|
||||||
|
```php
|
||||||
|
$stmt = $conn->prepare("SELECT * FROM users WHERE email = ?");
|
||||||
|
$stmt->bind_param("s", $email);
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
$row = $result->fetch_assoc();
|
||||||
|
$stmt->close();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example 1: Simple SELECT (admin_members.php)
|
||||||
|
|
||||||
|
### Current Code
|
||||||
|
```php
|
||||||
|
$stmt = $conn->prepare("SELECT user_id, first_name, last_name, tel_cell, email, dob, accept_indemnity FROM membership_application");
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
|
||||||
|
// Then in HTML/JS loop:
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
// display row
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using DatabaseService
|
||||||
|
```php
|
||||||
|
// Simple - get all records
|
||||||
|
$members = $db->select("SELECT user_id, first_name, last_name, tel_cell, email, dob, accept_indemnity FROM membership_application");
|
||||||
|
|
||||||
|
// In HTML/JS loop:
|
||||||
|
foreach ($members as $row) {
|
||||||
|
// display row
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- No manual `bind_param()`, `execute()`, `close()` needed
|
||||||
|
- Returns array directly
|
||||||
|
- Automatic error tracking via `$db->getLastError()`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example 2: SELECT with Parameters (validate_login.php)
|
||||||
|
|
||||||
|
### Current Code
|
||||||
|
```php
|
||||||
|
$query = "SELECT * FROM users WHERE email = ?";
|
||||||
|
$stmt = $conn->prepare($query);
|
||||||
|
$stmt->bind_param("s", $email);
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
|
||||||
|
if ($result->num_rows == 1) {
|
||||||
|
$row = $result->fetch_assoc();
|
||||||
|
// use $row
|
||||||
|
}
|
||||||
|
$stmt->close();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using DatabaseService
|
||||||
|
```php
|
||||||
|
$user = $db->selectOne(
|
||||||
|
"SELECT * FROM users WHERE email = ?",
|
||||||
|
[$email],
|
||||||
|
"s" // s = string type
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
// use $user - returns false if no row found
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- One-liner for single row
|
||||||
|
- Handles null checks automatically
|
||||||
|
- Type specification clear in parameters
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example 3: INSERT (validate_login.php)
|
||||||
|
|
||||||
|
### Current Code
|
||||||
|
```php
|
||||||
|
$query = "INSERT INTO users (email, first_name, last_name, profile_pic, password, is_verified) VALUES (?, ?, ?, ?, ?, ?)";
|
||||||
|
$stmt = $conn->prepare($query);
|
||||||
|
$is_verified = 1;
|
||||||
|
$stmt->bind_param("sssssi", $email, $first_name, $last_name, $picture, $password, $is_verified);
|
||||||
|
if ($stmt->execute()) {
|
||||||
|
$user_id = $conn->insert_id; // ❌ Bug: insert_id from $conn, not $stmt
|
||||||
|
// use $user_id
|
||||||
|
}
|
||||||
|
$stmt->close();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using DatabaseService
|
||||||
|
```php
|
||||||
|
$user_id = $db->insert(
|
||||||
|
"INSERT INTO users (email, first_name, last_name, profile_pic, password, is_verified) VALUES (?, ?, ?, ?, ?, ?)",
|
||||||
|
[$email, $first_name, $last_name, $picture, $password, 1],
|
||||||
|
"sssssi"
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($user_id) {
|
||||||
|
// $user_id contains the auto-increment ID
|
||||||
|
} else {
|
||||||
|
$error = $db->getLastError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Returns insert ID directly
|
||||||
|
- Automatic error handling
|
||||||
|
- Cleaner parameter list
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example 4: UPDATE (admin_members.php)
|
||||||
|
|
||||||
|
### Current Code
|
||||||
|
```php
|
||||||
|
$user_id = intval($_POST['user_id']);
|
||||||
|
$stmt = $conn->prepare("UPDATE membership_application SET accept_indemnity = 1 WHERE user_id = ?");
|
||||||
|
if ($stmt) {
|
||||||
|
$stmt->bind_param("i", $user_id);
|
||||||
|
$stmt->execute();
|
||||||
|
$stmt->close();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using DatabaseService
|
||||||
|
```php
|
||||||
|
$user_id = intval($_POST['user_id']);
|
||||||
|
$affectedRows = $db->update(
|
||||||
|
"UPDATE membership_application SET accept_indemnity = 1 WHERE user_id = ?",
|
||||||
|
[$user_id],
|
||||||
|
"i"
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($affectedRows !== false) {
|
||||||
|
// Updated successfully, $affectedRows = number of rows changed
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Returns affected row count
|
||||||
|
- No manual statement closing
|
||||||
|
- Error available via `$db->getLastError()`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example 5: COUNT / EXISTS
|
||||||
|
|
||||||
|
### Current Pattern (Need 3 lines)
|
||||||
|
```php
|
||||||
|
$stmt = $conn->prepare("SELECT COUNT(*) as count FROM users WHERE email = ?");
|
||||||
|
$stmt->bind_param("s", $email);
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
$row = $result->fetch_assoc();
|
||||||
|
if ($row['count'] > 0) { /* exists */ }
|
||||||
|
$stmt->close();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using DatabaseService (One line)
|
||||||
|
```php
|
||||||
|
$exists = $db->exists("users", "email = ?", [$email], "s");
|
||||||
|
if ($exists) {
|
||||||
|
// User exists
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Boolean result
|
||||||
|
- Intent is clear
|
||||||
|
- One-liner
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example 6: Multiple Rows with Filtering
|
||||||
|
|
||||||
|
### Current Code
|
||||||
|
```php
|
||||||
|
$status = 'active';
|
||||||
|
$stmt = $conn->prepare("SELECT * FROM members WHERE status = ? ORDER BY last_name ASC");
|
||||||
|
$stmt->bind_param("s", $status);
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
$members = [];
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$members[] = $row;
|
||||||
|
}
|
||||||
|
$stmt->close();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using DatabaseService
|
||||||
|
```php
|
||||||
|
$members = $db->select(
|
||||||
|
"SELECT * FROM members WHERE status = ? ORDER BY last_name ASC",
|
||||||
|
['active'],
|
||||||
|
"s"
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Returns array directly
|
||||||
|
- No loop needed
|
||||||
|
- 2 lines vs 8 lines
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example 7: Error Handling
|
||||||
|
|
||||||
|
### Current Pattern
|
||||||
|
```php
|
||||||
|
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
|
||||||
|
if (!$stmt) {
|
||||||
|
echo "Prepare failed: " . $conn->error;
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
$stmt->bind_param("i", $id);
|
||||||
|
if (!$stmt->execute()) {
|
||||||
|
echo "Execute failed: " . $stmt->error;
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using DatabaseService
|
||||||
|
```php
|
||||||
|
$user = $db->selectOne("SELECT * FROM users WHERE id = ?", [$id], "i");
|
||||||
|
if ($user === false) {
|
||||||
|
$error = $db->getLastError();
|
||||||
|
error_log("Database error: " . $error);
|
||||||
|
// handle error
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Error handling centralized
|
||||||
|
- No null checks for each step
|
||||||
|
- Debug via `$db->getLastQuery()`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example 8: Transactions
|
||||||
|
|
||||||
|
### Current Pattern
|
||||||
|
```php
|
||||||
|
$conn->begin_transaction();
|
||||||
|
try {
|
||||||
|
$stmt = $conn->prepare("INSERT INTO orders ...");
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("UPDATE inventory ...");
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$conn->commit();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$conn->rollback();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using DatabaseService
|
||||||
|
```php
|
||||||
|
$db->beginTransaction();
|
||||||
|
|
||||||
|
$order_id = $db->insert("INSERT INTO orders ...", [...], "...");
|
||||||
|
if ($order_id === false) {
|
||||||
|
$db->rollback();
|
||||||
|
exit("Order creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
$updated = $db->update("UPDATE inventory ...", [...], "...");
|
||||||
|
if ($updated === false) {
|
||||||
|
$db->rollback();
|
||||||
|
exit("Inventory update failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
$db->commit();
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Unified transaction API
|
||||||
|
- Built-in error checking
|
||||||
|
- Clean rollback on failure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Specification Reference
|
||||||
|
|
||||||
|
When using DatabaseService methods, specify parameter types:
|
||||||
|
|
||||||
|
| Type | Meaning | Example |
|
||||||
|
|------|---------|---------|
|
||||||
|
| `"i"` | Integer | `user_id = 5` |
|
||||||
|
| `"d"` | Double/Float | `price = 19.99` |
|
||||||
|
| `"s"` | String | `email = 'test@example.com'` |
|
||||||
|
| `"b"` | Blob | Binary data |
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```php
|
||||||
|
// Single parameter
|
||||||
|
$db->select("SELECT * FROM users WHERE id = ?", [123], "i");
|
||||||
|
|
||||||
|
// Multiple parameters
|
||||||
|
$db->select(
|
||||||
|
"SELECT * FROM users WHERE email = ? AND status = ?",
|
||||||
|
["test@example.com", "active"],
|
||||||
|
"ss"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mixed types
|
||||||
|
$db->select(
|
||||||
|
"SELECT * FROM orders WHERE user_id = ? AND total > ? AND date = ?",
|
||||||
|
[5, 100.50, "2025-01-01"],
|
||||||
|
"ids" // integer, double, string
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Migration Path
|
||||||
|
|
||||||
|
### Phase 1: New Code
|
||||||
|
Start using `$db` for all new features and AJAX endpoints.
|
||||||
|
|
||||||
|
### Phase 2: High-Traffic Files
|
||||||
|
Refactor popular files:
|
||||||
|
1. `validate_login.php` - Login is critical
|
||||||
|
2. `functions.php` - Helper functions
|
||||||
|
3. `admin_members.php`, `admin_payments.php` - Admin pages
|
||||||
|
|
||||||
|
### Phase 3: Gradual Rollout
|
||||||
|
As each file is refactored, commit and test thoroughly before moving to next.
|
||||||
|
|
||||||
|
### Phase 4: Full Migration
|
||||||
|
Eventually all procedural `$conn->prepare()` patterns replaced.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Benefits Summary
|
||||||
|
|
||||||
|
| Aspect | Before | After |
|
||||||
|
|--------|--------|-------|
|
||||||
|
| Lines per query | 5-8 | 1-3 |
|
||||||
|
| Error handling | Manual checks | Automatic |
|
||||||
|
| Type safety | bind_param() | Parameter array |
|
||||||
|
| Statement closing | Manual | Automatic |
|
||||||
|
| Insert ID handling | `$conn->insert_id` (buggy) | Direct return |
|
||||||
|
| Debugging | Check multiple vars | `getLastError()`, `getLastQuery()` |
|
||||||
|
| Consistency | Varies | Unified API |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. Start with one file (e.g., `admin_members.php`)
|
||||||
|
2. Convert simple queries first
|
||||||
|
3. Test thoroughly
|
||||||
|
4. Commit and move to next file
|
||||||
|
5. Keep `$conn` available for complex queries that don't fit the standard patterns
|
||||||
|
|
||||||
|
The `$db` service makes your code **cleaner, safer, and easier to maintain**.
|
||||||
Reference in New Issue
Block a user