Database
PlatoPHP provides MySQL/MariaDB, ClickHouse, and MongoDB drivers. Connections are opened lazily by the first real query and are managed across process boundaries by plato\runtime.
Configuration
// app/config/database.php
return [
'default' => 'mysql',
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => $_ENV['DB_MASTER_HOST'],
'database' => $_ENV['DB_DATABASE'],
'username' => $_ENV['DB_USERNAME'],
'password' => $_ENV['DB_PASSWORD'],
'charset' => 'utf8mb4',
],
],
];
Query builder
use plato\database\db;
$users = db::table('user')
->select('id', 'name')
->where('status', 1)
->where_in('role', ['admin', 'editor'])
->order_by('id', 'desc')
->page(2, 20)
->get();
$user = db::table('user')->where('id', 7)->first();
$id = db::table('user')->insert(['name' => 'Ada']);
$changed = db::table('user')->where('id', 7)->update(['status' => 1]);
$deleted = db::table('user')->where('id', 7)->delete();
Values use prepared statement bindings by default. Pass values as bindings to where_raw(), having_raw(), and raw statements as well; never interpolate user input into SQL.
Transactions and replicas
db::transaction(function ()
{
db::table('account')->where('id', 1)->update(['balance' => db::raw('balance - 100')]);
db::table('account')->where('id', 2)->update(['balance' => db::raw('balance + 100')]);
}, 3);
Ordinary reads may use a replica; on_master() forces the primary. cursor() streams rows and chunk() processes bounded batches. Connection configuration includes slow-query thresholds, reconnect policy, and an optional SELECT ceiling.