Code restructure push
This commit is contained in:
368
docs/DATABASE_SERVICE_EXAMPLES.md
Normal file
368
docs/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