nette/database
Nette Database is a lightweight PHP database layer with a fluent SQL builder, safe parameter binding, and handy helpers for querying, fetching, and working with result sets. Includes connections, transactions, and simple caching for robust apps.
Installation:
composer require nette/database
Add to your Laravel service provider (e.g., AppServiceProvider):
$this->app->bind('db', function ($app) {
return new \Nette\Database\Connection(
$app['config']['database.connections.mysql']['dsn'],
$app['config']['database.connections.mysql']['username'],
$app['config']['database.connections.mysql']['password']
);
});
First Query:
$db = app('db');
$users = $db->table('users')->fetchAll();
Basic CRUD:
// Insert
$db->table('users')->insert(['name' => 'John', 'email' => 'john@example.com']);
// Update
$db->table('users')->where('id', 1)->update(['name' => 'Updated']);
// Delete
$db->table('users')->where('id', 1)->delete();
Replace Eloquent queries with Nette’s fluent API:
$results = $db->table('users')
->where('active', true)
->order('created_at DESC')
->limit(10)
->fetchAll();
Leverage method chaining for complex queries:
$activeUsers = $db->table('users')
->where('active', true)
->join('orders', 'users.id = orders.user_id')
->where('orders.status', 'completed')
->group('users.id')
->orderBy('orders.total DESC')
->fetchPairs('id', 'name');
Use transaction() for atomic operations:
$db->transaction(function ($db) {
$db->table('accounts')->where('id', 1)->update(['balance' => $balance - 100]);
$db->table('accounts')->where('id', 2)->update(['balance' => $balance + 100]);
});
Fetch a single row and manipulate it:
$user = $db->table('users')->get(['id' => 1]);
$user->name = 'Updated Name';
$user->update();
Inspect database structure dynamically:
$table = $db->getStructure()->getTable('users');
$columns = $table->getColumns();
foreach ($columns as $column) {
echo $column->getName() . ': ' . $column->getType() . "\n";
}
Override default data type handling:
$db->getConnection()->setRowNormalizer(function ($row) {
$row['created_at'] = Carbon::parse($row['created_at']);
return $row;
});
Catch specific database errors:
try {
$db->transaction(function ($db) {
// Risky operation
});
} catch (\Nette\Database\DeadlockException $e) {
// Retry logic
$this->retryTransaction();
}
Use Nette’s SqlBuilder for raw SQL generation:
$sql = $db->table('users')->select('id', 'name')->getSql();
$query = DB::select($sql);
Parameter Binding Quirks:
IN() with raw arrays; use Selection::fromArray() instead:
$db->table('users')->where('id IN (?)', [1, 2, 3]); // ❌ Bypasses binding
$selection = $db->table('users')->where('id', [1, 2, 3]); // ✅ Safe
BC Breaks in v3.x:
fetch() now returns null instead of false for empty results.normalizeRow() converts 0000-00-00 dates to null (affects legacy apps).Driver-Specific Behaviors:
LIMIT/OFFSET support; use applyLimit() carefully.OFFSET-FETCH.OciDriver for PL/SQL stored procedures.Transactions:
transaction() calls are allowed but require explicit handling:
$db->transaction(function ($db) use ($db) {
$db->transaction(function ($db) { /* Inner transaction */ });
});
Performance:
convertBoolean/convertDateTime if not needed to reduce overhead:
$db->getConnection()->setOptions(['convertBoolean' => false]);
Enable SQL Logging:
$db->getConnection()->setDebugMode(true);
// Check Tracy Debugger or Laravel logs for raw SQL.
Use getLastQueryString():
$sql = $db->getConnection()->getLastQueryString();
logger($sql);
Connection Panel: Install Tracy for a visual query inspector:
\Nette\Database\Helpers::initializeTracy($db);
Handle Deadlocks Gracefully:
try {
$db->transaction(...);
} catch (\Nette\Database\DeadlockException $e) {
$this->retryWithBackoff();
}
Custom Drivers:
Extend \Nette\Database\Driver for unsupported databases (e.g., MongoDB):
class MongoDriver extends Driver {}
Query Preprocessing:
Override SqlPreprocessor for custom syntax:
$db->getConnection()->setPreprocessor(new class extends \Nette\Database\SqlPreprocessor {
protected function formatValue($value) { /* Custom logic */ }
});
Row Events:
Listen to row updates via ActiveRow events:
$user->onUpdate[] = function ($row) {
// Post-update logic
};
Laravel Integration:
Bind Nette’s Connection to Laravel’s DB facade:
DB::extend('nette', function ($config, $name) {
return new \Nette\Database\Connection($config['dsn'], $config['username'], $config['password']);
});
Default Options:
convertBoolean: true (converts TINYINT(1) to bool).convertDateTime: true (returns Nette\Database\DateTime).$db->getConnection()->setOptions(['convertDateTime' => false]);
Case Sensitivity:
quote() for column/table names in case-sensitive databases (e.g., PostgreSQL):
$db->table($db->quote('User'))->where($db->quote('name'), 'John');
PHP 8.5+:
strict_types=1 for type safety:
declare(strict_types=1);
How can I help you explore Laravel packages today?