Database Providers
Database connections, drivers, query services and schema grammar providers.
Responsibility
Registers shared database infrastructure: DatabaseConfig, ConnectionInterface, Database, DatabaseDriverInterface, Schema, SchemaCompiler and SchemaGrammarInterface. Concrete providers register driver and grammar implementations: MysqlDatabaseServiceProvider, PdoDatabaseServiceProvider, OdbcDatabaseServiceProvider and SqliteDatabaseServiceProvider.
Driver layer
Supported driver values are mysql, pdo and odbc. PDO can use explicit dialects; the skeleton SQLite setup uses DB_DRIVER=pdo with DB_DIALECT=sqlite and an SQLite DSN. There is no DB_DRIVER=sqlite driver enum.
Database config
Application database configuration lives in app/Config/Database.php and reads environment variables into database.default and database.connections.default.
# SQLite skeleton/local setup
DB_DRIVER=pdo
DB_DIALECT=sqlite
DB_DSN=sqlite:storage/skeleton.sqlite
# MySQL setup
DB_DRIVER=mysql
DB_DIALECT=mysql
DB_HOST=localhost
DB_PORT=3306
DB_NAME=app
DB_USER=root
DB_PASS=
Database service
Use Database for high-level selects, statements, cursors and transactions. Use DatabaseDriverInterface only when a component needs the lower-level framework driver API.
use Lemonade\Framework\Database\Database;
final class ExampleRepository
{
public function __construct(
private readonly Database $db,
) {}
public function store(string $name, string $payload): int
{
return $this->db->statement(
'INSERT INTO example_job (name, payload, created_at) VALUES (?, ?, ?)',
[$name, $payload, time()],
);
}
}
Driver service
DatabaseDriverInterface exposes the compatibility driver methods used by models, validation rules and lower-level integrations. query() returns a database result or false, so application code should check failures explicitly when using this layer directly.
use Lemonade\Framework\Database\DatabaseDriverInterface;
$driver = $container->get(DatabaseDriverInterface::class);
$result = $driver->query(
'UPDATE example_job SET name = ? WHERE id = ?',
['Updated name', 1],
);
if ($result === false) {
// Handle query failure.
}
Schema layer
Schema uses the active SchemaGrammarInterface resolved from database configuration. Define tables through TableBlueprint; the grammar handles database-specific SQL differences.
use Lemonade\Framework\Database\Schema\Blueprint\TableBlueprint;
use Lemonade\Framework\Database\Schema\Schema;
$schema = $container->get(Schema::class);
$schema->create('example_job', static function (TableBlueprint $table): void {
$table->id();
$table->string('name', 120);
$table->longText('payload');
$table->unsignedInteger('created_at');
$table->index(['name', 'created_at'], 'idx_example_job_name_created', ifNotExists: true);
}, ifNotExists: true);
Grammar behavior
MySQL grammar can keep indexes inline in CREATE TABLE. SQLite grammar may compile create-table into multiple statements: first CREATE TABLE, then CREATE INDEX IF NOT EXISTS for plain indexes. Schema::compileCreate() stays string-based for BC; compileCreateStatements() exists for multi-statement database differences.
Queue relation
The database queue transport uses the same database stack. queue:install creates queue tables through Schema and TableBlueprint, so the same command works for the local SQLite skeleton setup and for MySQL setups.
SQLite runtime
SQLite requires PHP extensions pdo_sqlite and sqlite3. Enable them in both CLI PHP and web PHP runtime. In Laragon those can use different php.ini files, so CLI commands may work while web requests fail with could not find driver until the web PHP configuration is updated too.