> For the complete documentation index, see [llms.txt](https://docs.phptravels.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.phptravels.com/support/for-developers/database-architecture.md).

# Database Architecture

**Table of Contents**

* Introduction
* Database Connection System
* Medoo ORM Overview
* Database Schema
* DB Operations
* Advanced Queries
* Best Practices
* Troubleshooting

***

**Introduction**

**PHPTRAVELS v10+** uses a robust database architecture built on MySQL/MariaDB with the Medoo PHP database framework. This lightweight ORM (Object-Relational Mapping) library provides a simple, secure, and efficient way to interact with the database while maintaining clean, readable code.

#### Why Medoo?

<figure><img src="/files/wGkjFsdZbFEBRLZr4wGq" alt=""><figcaption></figcaption></figure>

**Lightweight & Fast**

* Only \~60KB in size with zero dependencies
* PDO-based for optimal performance
* Minimal overhead compared to heavy ORMs

**Security First**

* Built-in SQL injection protection through prepared statements
* Automatic parameter binding and escaping
* No raw SQL strings in production code

**Developer Friendly**

* Intuitive array-based syntax
* Chainable methods for complex queries
* Comprehensive error handling
* Multi-database support (MySQL, MariaDB, PostgreSQL, SQLite)

***

### Database Connection System

#### Environment Configuration (.env)

PHPTRAVELS v10 uses environment variables for database configuration, ensuring security and portability across different environments (development, staging, production).

**Location:** `/v10/.env`

```ini
# Database Configuration
DB_TYPE=mysql
DB_HOST=localhost
DB_DATABASE=v10
DB_USERNAME=root
DB_PASSWORD=root
```

**Configuration Parameters:**

| Parameter     | Description                                        | Default   |
| ------------- | -------------------------------------------------- | --------- |
| `DB_TYPE`     | Database engine (mysql, mariadb, sqlite, pgsql)    | mysql     |
| `DB_HOST`     | Database server hostname or IP address             | localhost |
| `DB_DATABASE` | Name of the database                               | v10       |
| `DB_USERNAME` | Database user with appropriate permissions         | root      |
| `DB_PASSWORD` | User password (use strong passwords in production) | -         |

#### Connection Initialization (config.php)

The central configuration file loads environment variables and establishes the database connection globally.

**Location:** `/config.php`

```php
<?php

use Medoo\Medoo;

// Load environment variables from .env file
$env = parse_ini_file('.env');

// Initialize Medoo database connection
$db = new Medoo([
    'type'     => $env['DB_TYPE'] ?? 'mysql',
    'host'     => $env['DB_HOST'] ?? 'localhost',
    'database' => $env['DB_DATABASE'],
    'username' => $env['DB_USERNAME'],
    'password' => $env['DB_PASSWORD'],
    'charset'  => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'port'     => 3306,
    'prefix'   => '', // Optional table prefix
    'option'   => [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false
    ]
]);
```

**Connection Flow Diagram:**

```
┌─────────────────────────────────────────────────────────────┐
│                    Application Start                        │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│   Load config.php (Included in index.php/module files)     │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│         Read .env file using parse_ini_file()               │
│   (Loads DB_HOST, DB_DATABASE, DB_USERNAME, DB_PASSWORD)   │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│      Initialize new Medoo([...]) with credentials          │
│             Create global $db variable                      │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│       Medoo establishes PDO connection to MySQL             │
│         (With error handling and UTF-8 charset)             │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│     Global $db variable available across application        │
│           Ready for database operations                     │
└─────────────────────────────────────────────────────────────┘
```

#### Global Accessibility

Once initialized in `config.php`, the `$db` variable is globally accessible throughout the application:

```php
// In any PHP file that includes config.php
require_once 'config.php';

// $db is now available for database operations
$users = $db->select("users", "*");
```

#### Connection Error Handling

```php
try {
    $db = new Medoo([
        'type'     => $env['DB_TYPE'] ?? 'mysql',
        'host'     => $env['DB_HOST'] ?? 'localhost',
        'database' => $env['DB_DATABASE'],
        'username' => $env['DB_USERNAME'],
        'password' => $env['DB_PASSWORD'],
    ]);

    // Test connection
    $db->query("SELECT 1")->fetchAll();

} catch (PDOException $e) {
    error_log("Database Connection Error: " . $e->getMessage());
    die("Unable to connect to database. Please check your configuration.");
}
```

***

### Medoo ORM Overview

Medoo provides an elegant, array-based API for database operations. Instead of writing raw SQL, you work with PHP arrays and objects.

#### Core Concepts

**1. Array-Based Syntax**

```php
// Traditional SQL
$sql = "SELECT * FROM users WHERE email = ? AND status = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute(['user@example.com', 1]);

// Medoo approach
$user = $db->get("users", "*", [
    "email" => "user@example.com",
    "status" => 1
]);
```

**2. Automatic Parameter Binding** All values are automatically escaped and bound as prepared statement parameters, preventing SQL injection.

**3. Method Chaining** Complex queries can be built incrementally using method chaining for readability.

#### Medoo Methods Reference

| Method      | Purpose                           | Returns           |
| ----------- | --------------------------------- | ----------------- |
| `select()`  | Retrieve multiple rows            | Array of rows     |
| `get()`     | Retrieve single row               | Associative array |
| `insert()`  | Insert new record                 | PDOStatement      |
| `update()`  | Update existing records           | PDOStatement      |
| `delete()`  | Delete records                    | PDOStatement      |
| `replace()` | Replace record (INSERT or UPDATE) | PDOStatement      |
| `has()`     | Check if record exists            | Boolean           |
| `count()`   | Count rows matching criteria      | Integer           |
| `sum()`     | Calculate sum of column           | Number            |
| `avg()`     | Calculate average                 | Number            |
| `max()`     | Find maximum value                | Mixed             |
| `min()`     | Find minimum value                | Mixed             |
| `query()`   | Execute raw SQL                   | PDOStatement      |

***

### Database Schema

PHPTRAVELS v10 uses a comprehensive relational database schema with 30+ tables organized into logical groups.

#### Schema Overview

```
┌────────────────────────────────────────────────────────────────┐
│                    PHPTRAVELS v10 Database                      │
│                      Schema Architecture                        │
└────────────────────────────────────────────────────────────────┘

┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│ Core Tables     │  │ Booking Tables  │  │ Content Tables  │
├─────────────────┤  ├─────────────────┤  ├─────────────────┤
│ • users         │  │ • bookings      │  │ • blogs         │
│ • settings      │  │ • flights       │  │ • blog_cats     │
│ • modules       │  │ • hotels        │  │ • cms           │
│ • currencies    │  │ • tours         │  │ • email_tpl     │
│ • languages     │  │ • cars          │  │ • notification  │
│ • countries     │  │ • transfers     │  │ • pages         │
└─────────────────┘  └─────────────────┘  └─────────────────┘

┌─────────────────┐  ┌─────────────────┐ 
│ Payment Tables  │  │ Logging Tables  │
├─────────────────┤  ├─────────────────┤  
│ • transactions  │  │ • logs_bookings │
│ • credits       │  │ • logs_searches │
│ • invoices      │  │ • logs_users    │
│ • refunds       │  │ • logs_webhooks │
└─────────────────┘  └─────────────────┘

┌─────────────────┐  ┌─────────────────┐
│ Location Data   │  │ Reference Data  │
├─────────────────┤  ├─────────────────┤
│ • locations     │  │ • airports      │
│ • cities        │  │ • airlines      │
│ • destinations  │  │ • amenities     │
└─────────────────┘  └─────────────────┘
```

#### Core Tables

**1. users** - User authentication and profiles

```sql
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(50) UNIQUE NOT NULL,
  `first_name` varchar(100) NOT NULL,
  `last_name` varchar(100) NOT NULL,
  `email` varchar(255) UNIQUE NOT NULL,
  `password` varchar(255) NOT NULL,
  `phone` varchar(20) DEFAULT NULL,
  `country` varchar(100) DEFAULT NULL,
  `city` varchar(100) DEFAULT NULL,
  `address` text DEFAULT NULL,
  `state` varchar(100) DEFAULT NULL,
  `po_box` varchar(20) DEFAULT NULL,
  `user_type` enum('customer','agent','admin') DEFAULT 'customer',
  `status` tinyint(1) DEFAULT 1,
  `banned` tinyint(1) DEFAULT 0,
  `email_verified` tinyint(1) DEFAULT 0,
  `email_verification_token` varchar(100) DEFAULT NULL,
  `reset_password_token` varchar(100) DEFAULT NULL,
  `reset_password_expires` datetime DEFAULT NULL,
  `last_login` timestamp NULL DEFAULT NULL,
  `created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_email` (`email`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_user_type` (`user_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

**Key Fields:**

* `user_id`: Unique external identifier (UUID format)
* `password`: Hashed using password\_hash() with PASSWORD\_BCRYPT
* `user_type`: Role-based access control (customer/agent/admin)
* `status`: Active (1) or inactive (0) account
* `email_verified`: Email confirmation status

**2. settings** - Global application configuration

**3. modules** - Enabled/disabled booking modules

**4. currencies** - Supported currencies with exchange rates

**5. languages** - Multi-language support

#### Booking Tables

**bookings** - Master booking records

```sql
CREATE TABLE `bookings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `invoice_id` varchar(255) UNIQUE NOT NULL,
  `booking_status` enum('confirmed','pending','cancelled') DEFAULT 'pending',
  `payment_status` enum('paid','unpaid','refunded') DEFAULT 'unpaid',
  `price_original` double NOT NULL,
  `price_markup` varchar(225) DEFAULT '',
  `agent_earning` varchar(255) DEFAULT '',
  `tax` text NOT NULL,
  `first_name` varchar(50) NOT NULL,
  `last_name` varchar(50) NOT NULL,
  `email` varchar(50) NOT NULL,
  `phone` varchar(15) NOT NULL,
  `adults` tinyint(4) DEFAULT 1,
  `childs` tinyint(4) DEFAULT 0,
  `infants` varchar(255) DEFAULT '',
  `booking_data` text NOT NULL,
  `transaction_id` varchar(255) DEFAULT '',
  `user_id` varchar(255) DEFAULT '',
  `payment_gateway` varchar(255) DEFAULT '',
  `module_type` varchar(255) DEFAULT 'hotels',
  `module` varchar(255) NOT NULL,
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_invoice` (`invoice_id`),
  KEY `idx_user` (`user_id`),
  KEY `idx_status` (`booking_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
```

#### Logging Tables

System maintains comprehensive audit logs:

* **logs\_bookings** - Booking lifecycle events
* **logs\_searches** - User search analytics
* **logs\_users** - Authentication and profile changes
* **logs\_webhooks** - External API webhook events

#### Scalability Design

The database schema is designed for horizontal scalability:

**Current Tables:** 30+ core tables **Expandable:** Schema supports unlimited growth through:

* Modular table design (add new booking types)
* Polymorphic relationships (flexible module system)
* JSON columns for dynamic data (booking\_data, user\_data)
* Partitioning support for large tables

***

### DB Operations

#### SELECT - Retrieving Data

**Basic Select - All Columns**

```php
// Get all users
$users = $db->select("users", "*");

// Result: Array of all user records
```

**Select Specific Columns**

```php
// Get only email and name
$users = $db->select("users", [
    "id",
    "first_name",
    "last_name",
    "email"
]);
```

**Select with WHERE Conditions**

```php
// Find user by email
$user = $db->get("users", "*", [
    "email" => "admin@phptravels.com"
]);

// Find all active users
$active_users = $db->select("users", "*", [
    "status" => 1,
    "banned" => 0
]);
```

**Select with Multiple Conditions (AND)**

```php
$users = $db->select("users", "*", [
    "user_type" => "agent",
    "status" => 1,
    "email_verified" => 1
]);

// Generated SQL (protected against injection):
// SELECT * FROM users WHERE user_type = 'agent' AND status = 1 AND email_verified = 1
```

**Select with OR Conditions**

```php
$users = $db->select("users", "*", [
    "OR" => [
        "user_type" => "admin",
        "user_type" => "agent"
    ]
]);
```

**Select with Comparison Operators**

```php
// Users created in last 30 days
$recent_users = $db->select("users", "*", [
    "created_at[>]" => date('Y-m-d H:i:s', strtotime('-30 days'))
]);

// Operators: [>], [>=], [<], [<=], [!] (not equal), [<>] (between)
```

**Select with LIKE (Pattern Matching)**

```php
// Find users with email ending in @gmail.com
$gmail_users = $db->select("users", "*", [
    "email[~]" => "%@gmail.com"
]);

// Operators: [~] (LIKE), [!~] (NOT LIKE)
```

**Select with LIMIT and ORDER**

```php
$latest_users = $db->select("users", "*", [
    "ORDER" => ["created_at" => "DESC"],
    "LIMIT" => 10
]);
```

**Select with Pagination**

```php
$page = 1;
$per_page = 20;
$offset = ($page - 1) * $per_page;

$users = $db->select("users", "*", [
    "LIMIT" => [$offset, $per_page],
    "ORDER" => ["id" => "ASC"]
]);
```

**Get Single Row**

```php
// Returns first matching row only
$user = $db->get("users", "*", [
    "email" => "user@example.com"
]);

// $user is associative array or null if not found
if ($user) {
    echo $user['first_name'];
}
```

#### INSERT - Creating Records

**Basic Insert**

```php
$db->insert("users", [
    "user_id" => uniqid('user_'),
    "first_name" => "John",
    "last_name" => "Doe",
    "email" => "john@example.com",
    "password" => password_hash("secure123", PASSWORD_BCRYPT),
    "user_type" => "customer",
    "status" => 1
]);

// Get inserted ID
$new_user_id = $db->id();
```

**Insert with Current Timestamp**

```php
$db->insert("bookings", [
    "invoice_id" => 'INV-' . time(),
    "user_id" => $user_id,
    "booking_status" => "pending",
    "payment_status" => "unpaid",
    "price_original" => 150.00,
    "created_at" => Medoo::raw("NOW()")
]);
```

**Bulk Insert**

```php
$db->insert("logs_searches", [
    [
        "user_id" => 1,
        "module" => "hotels",
        "search_query" => json_encode($params),
        "created_at" => date('Y-m-d H:i:s')
    ],
    [
        "user_id" => 2,
        "module" => "flights",
        "search_query" => json_encode($params2),
        "created_at" => date('Y-m-d H:i:s')
    ]
]);
```

#### UPDATE - Modifying Records

**Basic Update**

```php
$db->update("users", [
    "first_name" => "Jane",
    "last_name" => "Smith"
], [
    "id" => 5
]);

// Returns PDOStatement
```

**Update with Multiple Conditions**

```php
$db->update("users", [
    "email_verified" => 1,
    "email_verification_token" => null
], [
    "email" => "user@example.com",
    "email_verification_token" => $token
]);
```

**Increment/Decrement Values**

```php
// Increment views
$db->update("blogs", [
    "views[+]" => 1  // Increment by 1
], [
    "id" => $blog_id
]);

// Decrement credits
$db->update("credits", [
    "balance[-]" => 50.00  // Decrement by 50
], [
    "user_id" => $user_id
]);
```

**Update with Raw SQL**

```php
$db->update("users", [
    "last_login" => Medoo::raw("NOW()")
], [
    "id" => $user_id
]);
```

#### DELETE - Removing Records

**Basic Delete**

```php
$db->delete("users", [
    "id" => 10
]);
```

**Delete with Multiple Conditions**

```php
// Delete inactive users older than 1 year
$db->delete("users", [
    "status" => 0,
    "created_at[<]" => date('Y-m-d', strtotime('-1 year'))
]);
```

**Soft Delete (Recommended)**

```php
// Instead of deleting, mark as deleted
$db->update("users", [
    "status" => 0,
    "deleted_at" => date('Y-m-d H:i:s')
], [
    "id" => $user_id
]);
```

#### EXISTS - Check Record Existence

**Check if User Exists**

```php
$exists = $db->has("users", [
    "email" => "test@example.com"
]);

if ($exists) {
    // Email already registered
}
```

#### COUNT - Counting Records

**Simple Count**

```php
$total_users = $db->count("users");
```

**Count with Conditions**

```php
$active_agents = $db->count("users", [
    "user_type" => "agent",
    "status" => 1
]);
```

***

### Advanced Queries

#### JOIN Operations

**INNER JOIN**

```php
$results = $db->select("bookings", [
    "[>]users" => ["user_id" => "user_id"]
], [
    "bookings.invoice_id",
    "bookings.booking_status",
    "bookings.created_at",
    "users.first_name",
    "users.last_name",
    "users.email"
], [
    "bookings.booking_status" => "confirmed"
]);
```

**LEFT JOIN**

```php
$results = $db->select("users", [
    "[<]bookings" => ["user_id" => "user_id"]
], [
    "users.email",
    "users.first_name",
    "bookings.invoice_id(booking_id)",
    "bookings.created_at(booking_date)"
]);
```

**Multiple JOINS**

```php
$results = $db->select("bookings", [
    "[>]users" => ["user_id" => "user_id"],
    "[>]transactions" => ["id" => "booking_id"]
], [
    "bookings.invoice_id",
    "users.email",
    "transactions.amount",
    "transactions.payment_gateway"
]);
```

#### Aggregation Functions

**SUM**

```php
$total_revenue = $db->sum("bookings", "price_markup", [
    "payment_status" => "paid",
    "created_at[>]" => date('Y-m-01')
]);

echo "Revenue this month: $" . number_format($total_revenue, 2);
```

**AVERAGE**

```php
$avg_booking_value = $db->avg("bookings", "price_original", [
    "booking_status" => "confirmed"
]);
```

**MAX/MIN**

```php
$highest_booking = $db->max("bookings", "price_original");
$lowest_booking = $db->min("bookings", "price_original");
```

#### GROUP BY and HAVING

**Group By with Count**

```php
$results = $db->select("bookings", [
    "module",
    "COUNT(*) AS total_bookings"
], [
    "GROUP" => "module",
    "ORDER" => ["total_bookings" => "DESC"]
]);
```

#### Raw SQL Queries

For complex queries not covered by Medoo methods:

```php
// Execute raw query
$stmt = $db->query("
    SELECT
        DATE(created_at) as date,
        COUNT(*) as bookings,
        SUM(price_markup) as revenue
    FROM bookings
    WHERE payment_status = 'paid'
    GROUP BY DATE(created_at)
    ORDER BY date DESC
    LIMIT 30
");

$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
```

***

### Best Practices

#### 1. Security

**Always Use Prepared Statements**

```php
// NEVER concatenate user input into queries
// BAD:
$user = $db->query("SELECT * FROM users WHERE email = '$email'")->fetch();

// GOOD:
$user = $db->get("users", "*", ["email" => $email]);
```

**Hash Passwords Properly**

```php
// During registration
$hashed = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
$db->insert("users", ["email" => $email, "password" => $hashed]);

// During login verification
$user = $db->get("users", "*", ["email" => $email]);
if ($user && password_verify($password, $user['password'])) {
    // Login successful
}
```

**Validate Input**

```php
// Sanitize and validate before database operations
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    die("Invalid email format");
}
```

#### 2. Performance Optimization

**Use Indexes**

```sql
-- Add indexes to frequently queried columns
CREATE INDEX idx_user_email ON users(email);
CREATE INDEX idx_booking_invoice ON bookings(invoice_id);
CREATE INDEX idx_booking_status ON bookings(booking_status, payment_status);
```

**Select Only Required Columns**

```php
// Instead of SELECT *
$users = $db->select("users", [
    "id",
    "first_name",
    "email"
], ["status" => 1]);
```

**Use LIMIT for Large Tables**

```php
// Paginate results
$bookings = $db->select("bookings", "*", [
    "LIMIT" => [0, 50],
    "ORDER" => ["created_at" => "DESC"]
]);
```

**Cache Frequent Queries**

```php
// Cache settings in session
if (!isset($_SESSION['app_settings'])) {
    $_SESSION['app_settings'] = $db->get("settings", "*", ["id" => 1]);
}
$settings = $_SESSION['app_settings'];
```

#### 3. Error Handling

**Always Use Try-Catch**

```php
try {
    $db->insert("users", [
        "email" => $email,
        "password" => $hashed_password
    ]);

    $user_id = $db->id();

} catch (PDOException $e) {
    // Log error
    error_log("Database Error: " . $e->getMessage());

    // Show user-friendly message
    die("Registration failed. Please try again.");
}
```

**Check for Errors**

```php
$result = $db->update("users", ["status" => 1], ["id" => $user_id]);

if ($db->error()[2]) {
    // Error occurred
    error_log("Update failed: " . $db->error()[2]);
}
```

#### 4. Data Integrity

**Use Transactions**

```php
try {
    // Start transaction
    $db->action(function($db) {

        // Insert booking
        $db->insert("bookings", $booking_data);
        $booking_id = $db->id();

        // Insert transaction
        $db->insert("transactions", [
            "booking_id" => $booking_id,
            "amount" => $amount,
            "status" => "completed"
        ]);

        // Update user credits
        $db->update("credits", [
            "balance[-]" => $amount
        ], [
            "user_id" => $user_id
        ]);

        // All queries succeed or all rollback
    });

} catch (Exception $e) {
    // Transaction rolled back automatically
    error_log("Transaction failed: " . $e->getMessage());
}
```

#### 5. Code Organization

**Create Repository Classes**

```php
class UserRepository {
    private $db;

    public function __construct($db) {
        $this->db = $db;
    }

    public function findByEmail($email) {
        return $this->db->get("users", "*", ["email" => $email]);
    }

    public function create($data) {
        $this->db->insert("users", $data);
        return $this->db->id();
    }

    public function updateLastLogin($user_id) {
        return $this->db->update("users", [
            "last_login" => Medoo::raw("NOW()")
        ], ["id" => $user_id]);
    }
}

// Usage
$userRepo = new UserRepository($db);
$user = $userRepo->findByEmail("admin@phptravels.com");
```

***

### Troubleshooting

#### Connection Issues

**Problem: "Access denied" Error**

```
Solution:
1. Verify .env credentials match MySQL user
2. Grant proper permissions:
   GRANT ALL PRIVILEGES ON v10.* TO 'username'@'localhost';
   FLUSH PRIVILEGES;
```

**Problem: "Database not found"**

```
Solution:
1. Create database manually:
   CREATE DATABASE v10 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
2. Run installation wizard at /install
```

**Problem: PDO Extension Not Loaded**

```
Solution:
1. Enable PDO in php.ini:
   extension=pdo_mysql
2. Restart Apache/Nginx
3. Verify: php -m | grep pdo
```

#### Query Issues

**Problem: Empty Results**

```php
// Debug query
$users = $db->select("users", "*", ["status" => 1]);
echo $db->last(); // Shows generated SQL
print_r($db->error()); // Shows any errors
```

**Problem: Slow Queries**

```php
// Enable query logging
$db->query("SET profiling = 1");
// Execute your queries
$profiles = $db->query("SHOW PROFILES")->fetchAll();
print_r($profiles);
```

#### Data Integrity

**Problem: Duplicate Entries**

```php
// Use UNIQUE constraints or check before insert
if (!$db->has("users", ["email" => $email])) {
    $db->insert("users", $data);
}
```

**Problem: Foreign Key Constraints**

```
Solution:
1. Ensure parent record exists before inserting child
2. Use ON DELETE CASCADE for automatic cleanup
3. Disable temporarily for bulk operations:
   SET FOREIGN_KEY_CHECKS=0;
```

#### Debugging Tools

**View Generated SQL**

```php
$db->select("users", "*", ["status" => 1]);
echo $db->last(); // Outputs: SELECT * FROM users WHERE status = 1
```

**Check Connection Status**

```php
$info = $db->info();
print_r($info);
// Returns: ['server' => ..., 'driver' => 'mysql', 'client' => ...]
```

**Error Information**

```php
$error = $db->error();
print_r($error);
// [0] => SQLSTATE code
// [1] => Driver error code
// [2] => Error message
```

***

### Additional Resources

**Official Medoo Documentation** <https://medoo.in/doc>

**PHPTRAVELS Database Migrations** Location: `/install/db.sql`

**Database Backup Command**

```bash
mysqldump -u root -p v10 > backup_$(date +%Y%m%d).sql
```

**Database Restore Command**

```bash
mysql -u root -p v10 < backup_20260109.sql
```

***

### Summary

The PHPTRAVELS v10 database architecture provides:

* Secure connection management via environment variables
* Efficient ORM operations through Medoo framework
* Scalable schema design supporting 30+ tables
* Comprehensive DB operations with array-based syntax
* Advanced query capabilities (JOINs, aggregations, transactions)
* Built-in security through prepared statements
* Performance optimization through indexing and caching
* Robust error handling and debugging tools

This architecture ensures data integrity, security, and performance while maintaining developer productivity through clean, readable code.
