Skip to content

marko/database-mysql

MySQL and MariaDB driver for the Marko framework database layer. Provides a MySQL-specific connection, query builder, SQL generator, and schema introspector --- all wired automatically when you install the package.

Implements ConnectionInterface, QueryBuilderInterface, SqlGeneratorInterface, and IntrospectorInterface from marko/database.

Terminal window
composer require marko/database-mysql

This automatically installs marko/database (the interface package) as a dependency.

Create a configuration file at config/database.php:

config/database.php
<?php
declare(strict_types=1);
return [
'driver' => 'mysql',
'host' => $_ENV['DB_HOST'] ?? 'localhost',
'port' => (int) ($_ENV['DB_PORT'] ?? 3306),
'database' => $_ENV['DB_DATABASE'] ?? 'marko',
'username' => $_ENV['DB_USERNAME'] ?? 'root',
'password' => $_ENV['DB_PASSWORD'] ?? '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
];

Set these in your .env file:

DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

This driver supports both MySQL 8.0+ and MariaDB 10.5+. Both are tested and fully supported.

The default charset is utf8mb4 which supports the full Unicode range including emojis. This is the recommended setting for new applications.

Marko enables MySQL strict mode by default. This ensures data integrity by rejecting invalid data rather than silently truncating or coercing values.

MySQL’s native JSON type is fully supported. Use the type: 'json' parameter in your #[Column] attribute:

use Marko\Database\Attributes\Column;
#[Column(type: 'json')]
public array $metadata = [];

Once configured, the MySQL driver is automatically used when you interact with the database. See marko/database for entity definition and repository usage.

use Marko\Database\Connection\ConnectionInterface;
class MyService
{
public function __construct(
private ConnectionInterface $connection,
) {}
public function doSomething(): void
{
// Connection is automatically MySQL
$result = $this->connection->query('SELECT * FROM users');
}
}

MySqlConnection implements ConnectionInterface and TransactionInterface. It wraps PDO with lazy connection --- the database connection is not established until the first query.

MethodDescription
query(string $sql, array $bindings = []): arrayExecute a query and return all rows as associative arrays
execute(string $sql, array $bindings = []): intExecute a statement and return the affected row count
prepare(string $sql): StatementInterfacePrepare a statement for repeated execution
lastInsertId(): intGet the last auto-increment ID
connect(): voidExplicitly open the database connection
disconnect(): voidClose the connection
isConnected(): boolCheck whether the connection is open

MySqlConnection also implements TransactionInterface:

MethodDescription
beginTransaction(): voidStart a transaction (throws on nested transactions)
commit(): voidCommit the current transaction
rollback(): voidRoll back the current transaction
inTransaction(): boolCheck whether a transaction is active
transaction(callable $callback): mixedExecute a callback inside a transaction --- auto-commits on success, rolls back on exception

MySqlQueryBuilder implements QueryBuilderInterface with a fluent API:

MethodDescription
table(string $table): staticSet the target table
select(string ...$columns): staticChoose columns to return
where(string $column, string $operator, mixed $value): staticAdd a WHERE condition
orWhere(string $column, string $operator, mixed $value): staticAdd an OR WHERE condition
whereIn(string $column, array $values): staticAdd a WHERE IN condition
whereNull(string $column): staticAdd a WHERE IS NULL condition
whereNotNull(string $column): staticAdd a WHERE IS NOT NULL condition
join(string $table, string $first, string $operator, string $second): staticInner join
leftJoin(string $table, string $first, string $operator, string $second): staticLeft join
rightJoin(string $table, string $first, string $operator, string $second): staticRight join
orderBy(string $column, string $direction = 'ASC'): staticOrder results
limit(int $limit): staticLimit result count
offset(int $offset): staticSkip rows
get(): arrayExecute and return all matching rows
first(): ?arrayExecute and return the first row, or null
insert(array $data): intInsert a row and return the last insert ID
update(array $data): intUpdate matching rows and return the affected count
delete(): intDelete matching rows and return the affected count
count(): intReturn the count of matching rows
raw(string $sql, array $bindings = []): arrayExecute raw SQL

MySqlGenerator implements SqlGeneratorInterface --- produces MySQL-specific DDL from schema diffs (used by the migration system).

Abstract TypeMySQL Type
integer / intINT
bigintBIGINT
smallintSMALLINT
tinyintTINYINT
stringVARCHAR(n) (default 255)
textTEXT
boolean / boolTINYINT(1)
datetimeDATETIME
dateDATE
timeTIME
timestampTIMESTAMP
decimalDECIMAL(10,2)
floatFLOAT
doubleDOUBLE
blob / binaryBLOB
jsonJSON

MySqlIntrospector implements IntrospectorInterface --- reads the live database schema via information_schema for use by the migration diff calculator.

MethodDescription
getTables(): arrayList all table names in the database
getTable(string $name): ?TableGet a full Table schema object (columns, indexes, foreign keys)
tableExists(string $name): boolCheck whether a table exists
getColumns(string $table): arrayGet column definitions for a table
getIndexes(string $table): arrayGet index definitions for a table
getForeignKeys(string $table): arrayGet foreign key definitions for a table
getPrimaryKey(string $table): arrayGet primary key column names for a table