LiteMySQLi is a lightweight, high-performance MySQLi wrapper for PHP 8.2+, designed to streamline database interactions with prepared statements, caching, transactions, and bulk operations.
Unlike heavy ORMs, LiteMySQLi focuses on speed, low overhead, and simplicity, while still offering a clean and safe API for most common SQL operations.
- β Minimalistic, intuitive API (single-file class)
- β Secure prepared statements with automatic type binding
- β Statement caching (FIFO, configurable limit, default: 128)
- β
Scalar helpers (
fetchValue(),fetchRow(),fetchAll()) - β
Bulk operations with
insertBatch()andexecuteMany() - β
Transaction support (
beginTransaction(),commit(),rollback(),easyTransaction()) - β
Streaming SELECT without mysqlnd (
selectNoMysqlnd()) - β
Raw SQL execution (
queryRaw(),queryRawMulti()) - β
Lightweight profiling (
countQueries()) - β
Deterministic cleanup of statements & connection (
close(),__destruct())
Simply include the LiteMySQLi.php file in your project:
require_once 'LiteMySQLi.php';$db = new LiteMySQLi('localhost', 'username', 'password', 'database');// Stewie checks if his world domination plan is ready
$plan = $db->fetchValue("SELECT status FROM evil_plans WHERE mastermind = ?", ['Stewie']);
if ($plan !== 'complete') {
echo "Blast! Foiled again by that insufferable dog, Brian!";
}$cup = $db->fetchRow("SELECT * FROM coffee WHERE status = ? LIMIT 1", ['hot']);
// probably null$adventures = $db->fetchAll("SELECT * FROM adventures WHERE duo = ?", ['Bill and Ted']);
foreach ($adventures as $adventure) {
echo "Adventure #" . $adventure['id'] . ": " . $adventure['title'] . " - most excellent!\n";
}foreach ($db->selectNoMysqlnd(
"SELECT * FROM naps WHERE status = ?", ['interrupted']
) as $row) {
echo $row['time'] . " - another debug at 3am\n";
}$id = $db->insert('users', [
'name' => 'Donald Duck',
'email' => 'donald@disney.com'
]);// Add the Griffin family in one go
$db->insertBatch('griffins', [
['name' => 'Peter', 'role' => 'Dad', 'hobby' => 'Drunken antics'],
['name' => 'Lois', 'role' => 'Mom', 'hobby' => 'Piano and sarcasm'],
['name' => 'Meg', 'role' => 'Daughter','hobby' => 'Being ignored'],
['name' => 'Chris', 'role' => 'Son', 'hobby' => 'Drawing weird stuff'],
['name' => 'Stewie', 'role' => 'Baby', 'hobby' => 'World domination'],
['name' => 'Brian', 'role' => 'Dog', 'hobby' => 'Martinis and novels'],
]);$db->update('employees', ['status' => 'fired'], 'name = ?', ['Homer Simpson']);
// doh!$db->delete('Canton', 'name = ?', ['Ryan Leaf']);if ($db->exists('users', 'email = ?', ['neo@matrix.io'])) {
echo "Whoa. Heβs already in the system.";
}$walkers = $db->countRows("SELECT * FROM zombies WHERE location = ?", ['Alexandria']);$db->beginTransaction();
try {
$db->insert('Cheers', ['name' => 'Sam Malone']);
$db->insert('Cheers', ['name' => 'Diane Chambers']);
$db->insert('Cheers', ['name' => 'Norm Peterson']);
$db->commit(); // where everybody knows your name
} catch (Throwable $e) {
$db->rollback(); // back to drinking alone
}// Successful transaction (committed)
$db->easyTransaction(function($db) {
// Insert player (parent)
$db->insert('players', ['name' => 'Tom Brady']);
// Child row references the just-created player via lastInsertId()
$db->insert('comebacks', ['player_id' => $db->lastInsertId(), 'score' => '28-3']);
});
// Failing transaction (rolled back automatically)
try {
$db->easyTransaction(function($db) {
// Looks great at halftime...
$db->insert('teams', ['name' => 'Atlanta Falcons', 'lead' => '28-3']);
// ...but something goes wrong β trigger rollback of everything above
throw new RuntimeException("Celebrating too early... rollback!");
});
} catch (\Throwable $e) {
// Already rolled back; no rows from this block were persisted
}$db->queryRaw("CREATE TEMPORARY TABLE time_travelers (id INT, name VARCHAR(50))");
$db->queryRaw("INSERT INTO time_travelers VALUES (1, 'Marty'), (2, 'Doc Brown')");
$res = $db->queryRaw("SELECT * FROM time_travelers");
while ($row = $res->fetch_assoc()) {
echo $row['id'] . ': ' . $row['name'] . PHP_EOL;
}
$res->free();$results = $db->queryRawMulti("
CREATE TEMPORARY TABLE gallaghers (id INT, name VARCHAR(50));
INSERT INTO gallaghers (id, name) VALUES (1, 'Frank'), (2, 'Lip'), (3, 'Fiona');
SELECT * FROM gallaghers;
");
foreach ($results as $res) {
if ($res instanceof mysqli_result) {
while ($row = $res->fetch_assoc()) {
echo $row['id'] . ' -> ' . $row['name'] . PHP_EOL;
}
$res->free();
}
}lastInsertId()-> returns the last AUTO_INCREMENT valueaffectedRows()-> number of rows affected by last querycountQueries($reset = false)-> number of executed queries (optionally reset)getLastError() / getLastErrorCode()-> retrieve last MySQL errorsetStatementCacheLimit($limit)-> change cache size or disable cachingclearStatementCache()-> free all cached prepared statementsclose()-> explicit cleanup (statements + connection)
LiteMySQLi defaults to strict error mode (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT),
which means all database errors throw mysqli_sql_exception immediately:
try {
$db->execute("INVALID SQL");
} catch (mysqli_sql_exception $e) {
echo "Database error: " . $e->getMessage();
}If you prefer to inspect errors manually (e.g. for logging or batch scripts), you can use the helper methods:
$db->execute("INVALID SQL");
if ($db->getLastErrorCode() !== 0) {
echo "Error code: " . $db->getLastErrorCode();
echo "Error message: " . $db->getLastError();
}getLastErrorCode()β last error code (0 if none).getLastError()β last error message (null if none).
These methods do not throw and can be used alongside or instead of exceptions.
- β‘ Blazing fast by design - minimal overhead, tiny call graph, and OPcache-friendly code paths.
- π Safety first - prepared statements everywhere, type-aware binding, no string concatenation footguns.
- πΎ Memory-lean - predictable allocations, no ORM hydration bloat or proxy objects.
- π§© Zero dependencies - a single ~60 KB PHP file; nothing else to install or maintain.
- π Shared-hosting friendly - runs anywhere PHP + MySQLi runs (perfect for budget and legacy hosts).
- β»οΈ Smart statement cache - FIFO cache reuses prepared statements for repeat queries to cut latency.
- π¦ Bulk at scale -
insertBatch()andexecuteMany()deliver high throughput for large datasets. - π§΅ Deterministic cleanup -
close()and a safe__destruct()ensure resources are freed promptly. - π§ͺ Strict error mode - leverages
MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICTto fail fast and loud. - π Lightweight profiling -
countQueries()gives you instant per-request query counts. - π Index awareness - optional
MYSQLI_REPORT_INDEXhelps surface βmissing/bad indexβ warnings early. - π Streams without mysqlnd -
selectNoMysqlnd()reads large result sets with tiny memory footprints. - π§° Pragmatic escape hatches -
queryRaw()andqueryRawMulti()for migrations and admin tasks. - π‘οΈ Transaction-strong - explicit
begin/commit/rollback+easyTransaction()convenience wrapper. - π§ No hidden magic - what you write is what runs; SQL remains front and center.
- π§° Drop-in adoption - keep your existing SQL and migrate one query at a time with near-zero risk.
- π Idempotent helpers -
fetchValue(),fetchRow(),fetchAll()cover 90% of day-to-day reads. - π§± Strict identifier quoting - safe table/column quoting via
quoteIdentifier*()utilities. - π Operations-ready - explicit resource freeing, predictable failure modes, and clean connection state.
- π§© Framework-agnostic - fits neatly into any codebase; PSR-4 compatible, no global state.
- π§ MariaDB/MySQL compatible - targets mainstream MySQL/MariaDB features, not vendor-specific quirks.
- β± Benchmark-friendly - simple API surface makes it easy to measure and tune hot paths.
- π§Ύ GPL-3.0-or-later - open source with a clear, permissive-for-FOSS licensing model.
- π§βπ» Built for PHP 8.2+ - typed properties, strict types, modern language features by default.
- π§ Config on your terms - adjustable statement cache size, strictness, and charset.
TL;DR: LiteMySQLi gives you raw SQL speed, modern safety, and production-grade ergonomics - without the ORM baggage.
Perfect for developers who want raw SQL power with modern safety and speed.
LiteMySQLi is released under the GNU General Public License v3.0 or later. See LICENSE for details.
Developed by Lars Grove Mortensen Β© 2025 Contributions and pull requests are welcome!
π If you find this library useful, give it a star on GitHub! π