Driver di database
merql separa il trasporto della connessione dal dialetto del database. Un adattatore DatabaseConnection esegue SQL tramite PDO o mysqli, mentre un Driver gestisce i metadati SQL specifici del motore di database e la quotatura degli identificatori. Sono disponibili driver integrati per MySQL e SQLite.
use Merql\Driver\DriverFactory;
$driver = DriverFactory::create($connection);
// Auto-detects MySQL or SQLite from the connection driver identity.
L'interfaccia Driver
Ogni driver implementa cinque metodi:
use Merql\Driver\Driver;
interface Driver
{
public function quoteIdentifier(string $name): string;
public function listTables(DatabaseConnection $connection): array;
public function readSchema(DatabaseConnection $connection, string $table): TableSchema;
public function readForeignKeys(DatabaseConnection $connection): array;
public function selectAll(string $table): string;
}
| Metodo | Scopo |
|---|---|
quoteIdentifier |
Quota il nome di una tabella o colonna per usarlo in SQL. |
listTables |
Restituisce tutte le tabelle utente nel database corrente. |
readSchema |
Legge i nomi e i tipi delle colonne, la chiave primaria e le chiavi univoche di una tabella. |
readForeignKeys |
Restituisce una mappa delle dipendenze tra tabelle figlie e tabelle padre. |
selectAll |
Crea una query SELECT * per una tabella. |
MysqlDriver
Usa query INFORMATION_SCHEMA per i metadati e la quotatura con backtick per gli identificatori.
use Merql\Driver\MysqlDriver;
$driver = new MysqlDriver();
$driver->quoteIdentifier('posts');
// `posts`
$driver->quoteIdentifier('my`table');
// `my``table`
$tables = $driver->listTables($connection);
// ['comments', 'posts', 'users']
$schema = $driver->readSchema($connection, 'posts');
// TableSchema with columns, primaryKey, uniqueKeys
$fks = $driver->readForeignKeys($connection);
// ['comments' => ['posts', 'users']]
L'elenco delle tabelle interroga INFORMATION_SCHEMA.TABLES, filtrato per il database corrente e il tipo BASE TABLE. La lettura dello schema interroga INFORMATION_SCHEMA.COLUMNS per le colonne e INFORMATION_SCHEMA.KEY_COLUMN_USAGE per le chiavi primarie e univoche.
SqliteDriver
Usa query PRAGMA per i metadati e la quotatura con virgolette doppie per gli identificatori.
use Merql\Driver\SqliteDriver;
$driver = new SqliteDriver();
$driver->quoteIdentifier('posts');
// "posts"
$driver->quoteIdentifier('my"table');
// "my""table"
$tables = $driver->listTables($connection);
// Queries sqlite_master, excludes sqlite_* internal tables.
$schema = $driver->readSchema($connection, 'posts');
// Uses PRAGMA table_info() and PRAGMA index_list().
$fks = $driver->readForeignKeys($connection);
// Uses PRAGMA foreign_key_list() for each table.
DriverFactory
DriverFactory rileva automaticamente il driver corretto da DatabaseConnection::driverName().
use Merql\Connection;
use Merql\Driver\DriverFactory;
$connection = Connection::mysql('127.0.0.1', 'mydb', 'root', '');
$driver = DriverFactory::create($connection);
// Returns MysqlDriver
$connection = Connection::sqlite(':memory:');
$driver = DriverFactory::create($connection);
// Returns SqliteDriver
Se l'identità del driver della connessione non viene riconosciuta, viene generata una RuntimeException con il messaggio Unsupported database driver: <name>. merql non include driver PostgreSQL.
Registrazione di driver personalizzati
Per database diversi da MySQL e SQLite, scrivi una classe che implementi Driver e registrala. PostgresDriver qui sotto indica la tua classe:
use Merql\Driver\DriverFactory;
DriverFactory::register('pgsql', PostgresDriver::class);
$connection = Connection::fromDsn('pgsql:host=localhost;dbname=mydb', 'user', 'pass');
$driver = DriverFactory::create($connection);
// Returns your PostgresDriver instance.
La classe del driver deve implementare l'interfaccia Driver. Il primo argomento di register() è l'identità del driver della connessione.
Ripristino
Per i test, ripristina la factory allo stato predefinito:
DriverFactory::reset();
// Reverts to only MySQL and SQLite drivers.
Helper di connessione
La classe Connection crea adattatori con impostazioni predefinite sensate. Gli adattatori PDO usano eccezioni in caso di errore, modalità di fetch associativa, prepared statement reali e valori recuperati convertiti in stringhe. L'adattatore mysqli imposta utf8mb4, usa la modalità eccezioni mysqli, prepared statement e normalizza i valori recuperati allo stesso formato stringa o null.
use Merql\Connection;
// MySQL.
$connection = Connection::mysql('127.0.0.1', 'my_database', 'root', 'password');
$connection = Connection::mysql('db.example.com', 'mydb', 'user', 'pass', port: 3307);
// MySQLi.
$connection = Connection::mysqli('127.0.0.1', 'my_database', 'root', 'password');
// SQLite.
$connection = Connection::sqlite(':memory:');
$connection = Connection::sqlite('/var/data/app.sqlite');
// Any MySQL or SQLite PDO DSN.
$connection = Connection::fromDsn('mysql:host=127.0.0.1;dbname=mydb;charset=utf8mb4', 'user', 'pass');
fromDsn() accetta qualsiasi DSN che PDO possa aprire, ma merql può acquisire snapshot e applicare modifiche solo tramite un driver registrato. Una connessione pgsql: si apre (se pdo_pgsql è installato), ma i costruttori di Merql::init(), Snapshotter, Applier e GuardedApplier chiamano DriverFactory::create(), che genera RuntimeException: Unsupported database driver: pgsql a meno che tu non abbia registrato un driver per esso o non ne passi uno.
Connection::sqlite() abilita anche automaticamente PRAGMA foreign_keys = ON, che SQLite richiede per l'applicazione dei vincoli di chiave esterna.
Dove vengono usati i driver
I driver sono usati in tutto merql:
- Snapshotter usa
listTables,readSchemaeselectAllper acquisire lo stato del database. - Applier usa
readForeignKeysper determinare l'ordine delle operazioni e passa il driver aSqlGeneratorper la quotatura degli identificatori. - SqlGenerator usa
quoteIdentifierper creare SQL sicuro.
Se passi una connessione a Snapshotter o Applier senza specificare un driver, DriverFactory::create() viene chiamato automaticamente.