lowyiyiu/ppmw

A modern, single-file, heavily typed PHP 8 PDO MySQL wrapper.

Maintainers

Package info

github.com/lowyiyiu/PPMW

pkg:composer/lowyiyiu/ppmw

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1 2026-05-10 19:54 UTC

This package is auto-updated.

Last update: 2026-05-10 20:01:01 UTC


README

A modern, single-file, heavily typed PHP 8.1+ PDO MySQL wrapper. Designed for simplicity, performance, and ease of use, with built-in PSR-3 logging support and a fluid query builder.

Features

  • Zero Configuration Boilerplate: Easy to set up and get running.
  • Fluent Query Builder: Chainable methods for building complex SQL queries securely.
  • Prepared Statements Default: 100% immune to SQL injection when using the query builder.
  • Memory Efficient: Support for PHP Generators (yield) to process massive datasets.
  • PSR-3 Logging: Automatically logs slow queries and database errors (bring your own logger).
  • Single File Drop-In: Install via Composer or download as a standalone, dependency-free file.

Installation

Option 1: Via Composer (Recommended)

composer require lowyiyiu/ppmw

Option 2: Manual Include

Download src/Database.php and include it directly in your script. It includes a built-in PSR-3 interface fallback, meaning it requires zero external dependencies.

require_once 'path/to/src/Database.php';

Initialization & Configuration

To start, instantiate the Database class with your connection array.

use LOWYIYIU\PPMW\Database;

$config = [
    'host'     => '127.0.0.1',  // Default: 127.0.0.1
    'port'     => 3306,         // Default: 3306
    'database' => 'my_app',     
    'username' => 'root',       
    'password' => 'secret',     
    'charset'  => 'utf8mb4',    // Default: utf8mb4
    'prefix'   => 'app_'        // Optional: Auto-prepended to table names
];

// Basic instantiation
$db = new Database($config);

// Advanced instantiation with PSR-3 Logger and custom Slow Query Threshold (in seconds)
// $db = new Database($config, $myPsr3Logger, 1.5);

Retrieving Data

PPMW offers a fluent query builder to fetch data easily.

Fetching Multiple Rows (get)

Returns an array of associative arrays.

$users = $db->from('users')->get();

Fetching a Single Row (getOne)

Applies a LIMIT 1 and returns a single associative array, or null if no record is found.

$user = $db->from('users')->where('id', 1)->getOne();

Fetching a Single Column Value (getValue)

Fetches exactly one specific column from one row. Useful for counts or specific lookups.

// Returns the integer count
$total = $db->getValue('COUNT(*)', 'users');

// Returns the email string
$email = $db->from('users')->where('id', 1)->getValue('email');

Fetching Large Datasets with Cursors (getCursor)

If you need to process thousands of rows, use getCursor(). It uses PHP Generators to fetch one row into memory at a time, preventing memory exhaustion.

$users = $db->from('users')->where('status', 'active')->getCursor();

foreach ($users as $user) {
    // Process $user row by row
}

Query Builder Methods

You can chain these methods together to build complex SQL statements before calling an execution method (get, update, delete, etc.).

Select & From

By default, PPMW selects *. You can specify columns using select().

$db->select('id', 'name', 'email')
   ->from('users')
   ->get();

// You can also use an alias
$db->from('users', 'u')->get();

Where Clauses

The where method is dynamic and handles operators and arrays automatically.

// Basic equality: WHERE status = 'active'
$db->from('users')->where('status', 'active');

// Custom operator: WHERE age > 18
$db->from('users')->where('age', '>', 18);

// IN clause: WHERE role IN ('admin', 'editor')
// PPMW automatically detects arrays and uses IN
$db->from('users')->where('role', ['admin', 'editor']);

// OR clauses
$db->from('users')
   ->where('status', 'active')
   ->orWhere('role', 'admin');

Sorting & Grouping

// ORDER BY created_at DESC
$db->from('users')->orderBy('created_at', 'DESC');

// GROUP BY role, status
$db->from('users')->groupBy('role', 'status');

Limit & Offset

// LIMIT 10 OFFSET 20
$db->from('users')->limit(10)->offset(20)->get();

Joins

PPMW automatically applies your table prefix to joined tables.

// INNER JOIN
$db->from('users')
   ->join('posts', 'users.id', '=', 'posts.user_id')
   ->get();

// LEFT JOIN
$db->from('users')
   ->leftJoin('profiles', 'users.id', '=', 'profiles.user_id')
   ->get();

Writing Data

Inserting

Pass an associative array of column-value pairs.

// Returns boolean true/false
$success = $db->insert('users', [
    'name'  => 'John Doe',
    'email' => 'john@example.com'
]);

// Returns the newly created auto-incrementing ID
$newId = $db->insertGetId('users', [
    'name'  => 'Jane Doe',
    'email' => 'jane@example.com'
]);

Updating

Always chain a where() clause before calling update(), otherwise you will update every row in the table.

// Returns the number of affected rows
$affected = $db->where('id', 1)->update('users', [
    'status' => 'inactive'
]);

Deleting

Like updating, ensure you chain a where() clause first.

// Returns the number of affected rows
$deleted = $db->where('status', 'banned')->delete('users');

Advanced Usage

Transactions

Safely execute multiple queries. If one fails, you can roll everything back.

try {
    $db->beginTransaction();

    $db->insert('users', ['name' => 'Alice']);
    $db->insert('profiles', ['user_id' => 1, 'bio' => 'Hello']);

    $db->commit();
} catch (\Exception $e) {
    $db->rollBack();
    // Handle error
}

Raw Queries

If the query builder isn't enough, you can execute raw SQL with prepared bindings.

// For SELECT queries returning data
$results = $db->rawQuery(
    "SELECT * FROM app_users WHERE age > ? AND status = ?", 
    [18, 'active']
);

// For execution queries (INSERT, UPDATE, DELETE, ALTER)
$success = $db->raw(
    "UPDATE app_users SET logins = logins + 1 WHERE id = ?", 
    [1]
);

Connection Management

// Disconnect (closes PDO connection)
$db->disconnect();

// Ping the server (returns true if alive, automatically reconnects if "MySQL gone away")
$isAlive = $db->ping();

// Get the raw PDO instance for native PDO methods
$pdo = $db->getPdo();

Debugging Utilities

// Get the last executed query string (with bindings populated for debugging)
$sql = $db->getLastQuery();

// Get the row count of the last executed statement
$count = $db->getRowCount();

Error Handling & Exceptions

PPMW throws specific exceptions that you can catch to handle errors gracefully:

  • LOWYIYIU\PPMW\DatabaseException: The base exception for the library.
  • LOWYIYIU\PPMW\DatabaseConnectionException: Thrown if the initial connection fails (e.g., bad credentials).
  • LOWYIYIU\PPMW\DatabaseQueryException: Thrown if a query has a syntax error or fails to execute.
use LOWYIYIU\PPMW\DatabaseConnectionException;

try {
    $db = new Database($config);
} catch (DatabaseConnectionException $e) {
    echo "Could not connect to database: " . $e->getMessage();
}

License

This project is licensed under the MIT License. See the LICENSE file for details.