efabrica / phoenix-mysql
MySQL adapter for Phoenix database migrations
1.0.0
2026-10-26 07:36 UTC
Requires
- php: ^8.4
- ext-pdo: *
- ext-pdo_mysql: *
- efabrica/phoenix-core: ^4.0
- efabrica/phoenix-pdo: ^1.0
Requires (Dev)
- phpunit/phpunit: ^9.5.11
- ramsey/uuid: ^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-26 08:43:49 UTC
README
MySQL adapter for Phoenix database migrations. It registers the mysql adapter and is built on the shared PDO base in efabrica/phoenix-pdo.
Requirements
- PHP 8.4+
ext-pdoandext-pdo_mysql- MySQL 5.7, 8.0, 8.4 or 9 (these versions are covered by the test suite, see
.github/workflows/phpunit.yml). MariaDB is not tested.
Installation
composer require efabrica/phoenix-core efabrica/phoenix-mysql
efabrica/phoenix-pdo is installed automatically as a dependency. The package registers the mysql adapter in Phoenix\Database\Adapter\AdapterFactory from its composer bootstrap, nothing else has to be wired up.
Setup in a project
- Create a configuration file
phoenix.php(orphoenix.yml,phoenix.neon,phoenix.json) in the project root:<?php return [ 'migration_dirs' => [ 'app' => __DIR__ . '/migrations', ], 'environments' => [ 'local' => [ 'adapter' => 'mysql', 'host' => '127.0.0.1', 'port' => 3306, 'username' => 'root', 'password' => 'secret', 'db_name' => 'my_app', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_general_ci', ], 'production' => [ 'adapter' => 'mysql', 'dsn' => 'mysql:dbname=my_app;host=db.internal;charset=utf8mb4', 'username' => 'migrator', 'password' => getenv('DB_PASSWORD'), ], ], 'default_environment' => 'local', 'log_table_name' => 'phoenix_log', ];
ymlandneonconfig files needsymfony/yamlresp.nette/neoninstalled. All configuration keys are described in the configuration docs. - Create and run migrations with the command runner
vendor/bin/phoenix:
Usevendor/bin/phoenix create "App\CreateUsers" vendor/bin/phoenix migrate vendor/bin/phoenix status vendor/bin/phoenix rollback-e productionto pick another environment and-c path/to/config.phpfor a config file elsewhere. The log table (log_table_name) is created automatically on the first run, you do not have to runinityourself. All commands are described in the commands docs, how to write migrations in the migrations docs. - The database user needs the privileges for what the migrations do:
CREATE,ALTER,DROP,INDEX,REFERENCESplusINSERT,UPDATE,DELETE,SELECTon the log table and on the tables you fill with data. The database itself has to exist, Phoenix does not create it.
Configuration options
| key | required | description |
|---|---|---|
adapter |
yes | mysql |
host, port |
yes (without dsn) |
server address, port is optional (default of the driver is 3306) |
db_name |
yes (without dsn) |
database name, it has to exist |
dsn |
no | full PDO dsn, e.g. mysql:dbname=my_app;host=localhost;charset=utf8mb4. When set, host, port, db_name and charset are not used for the connection (charset and collation still apply as defaults for new tables) |
username, password |
no | credentials |
charset |
no | default charset of created tables and columns, default utf8mb4 |
collation |
no | default collation of created tables and columns, when not set the server default collation of the charset is used |
version |
no | server version, e.g. 8.0.36. When not set, it is read from the server on connect. It decides which features the query builder uses (see below) |
What the adapter supports
- tables with charset, collation, comment and
AUTO_INCREMENTstart value (setAutoIncrement()), renaming and copying tables (CREATE TABLE ... LIKE, optionally with data) - columns with
signed(unsignedwhen false),null,default,charset,collation,comment,after/firstposition, autoincrement, renaming and changing columns in onealter - primary keys over one or more columns, including adding a primary key to an existing table
- indexes: normal,
UNIQUEandFULLTEXT, methodsBTREEandHASH, prefix length andDESCorder per index column - foreign keys with
ON DELETE/ON UPDATEactions, unique constraints - views (
view(),replaceView(),dropView()) dumpanddiffcommands read the complete structure back frominformation_schema
Column type mapping
| Phoenix type | MySQL type | note |
|---|---|---|
string |
varchar(255) |
length configurable |
char |
char(255) |
|
tinytext, text, mediumtext, longtext |
the same | |
tinyinteger, smallinteger, mediuminteger, integer, biginteger |
tinyint(4), smallint(6), mediumint(9), int(11), bigint(20) |
display width configurable, MySQL 8 ignores it |
boolean |
tinyint(1) |
|
bit |
bit(32) |
|
numeric, decimal |
decimal(10,0) |
precision and scale configurable |
float, double |
float(10,0), double(10,0) |
|
date, time, datetime, timestamp, year |
the same | DEFAULT_VALUE_CURRENT_TIMESTAMP is supported for datetime and timestamp |
uuid |
char(36) |
read back as uuid by dump / diff |
json |
json on MySQL 5.7.8+, text on older servers |
decided by version |
enum, set |
enum(...), set(...) |
values from the values setting |
binary, varbinary |
binary(255), varbinary(255) |
|
tinyblob, blob, mediumblob, longblob |
the same | |
point, line, polygon |
point, linestring, polygon |
Limitations and things to watch
timestamptzis not a MySQL type. It is passed through unchanged and the server rejects it, usedatetimeortimestamp.jsondepends on the server version. Withversionset to something below 5.7.8 (or an old server) ajsoncolumn becomestext. Setversionexplicitly when the migrations are generated on one server and executed on another, so that both produce the same statements.utf8vsutf8mb3. MySQL 8.0.30+ reports theutf8charset asutf8mb3. The adapter normalizes it back toutf8when it loads the structure, sodumpanddiffdo not report a bogus change. Preferutf8mb4for new tables anyway.- Integer display width.
int(11)etc. is written into DDL, MySQL 8 silently drops it. Whendumpreads an integer column without width it fills the default (11forint,20forbigint, ...) to keep diffs stable. - Nullable
timestamp. A nullabletimestampcolumn without default is created asNULL DEFAULT NULL, so MySQL does not add the implicitDEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.ON UPDATE CURRENT_TIMESTAMPitself cannot be expressed in a migration. booleandefault. A boolean column always gets a default (0when none is set).- Index comments, partitioning, generated columns, check constraints, triggers, stored routines are not part of the migration API. Use
$this->execute()with raw SQL in a migration for those. - Foreign key checks stay on unless the migration calls
$this->checkForeignKeysOff()(SET FOREIGN_KEY_CHECKS = 0) and$this->checkForeignKeysOn()again, so the order of statements in a migration has to respect the constraints. - Migrations are not wrapped in a transaction (MySQL DDL would commit implicitly anyway), so a failing migration leaves the already executed statements applied and is not logged as executed. Fix the state by hand or keep migrations small enough to be re-run.
- The adapter uses
PDO::ERRMODE_SILENTand turns errors intoDatabaseQueryExecuteExceptionwith the SQLSTATE and the failing query in the message.
Tests
Tests need a running MySQL, connection is taken from the PHOENIX_MYSQL_* environment variables (see phpunit.xml.dist). CI runs the suite against MySQL 5.7, 8.0, 8.4 and 9 (see .github/workflows/phpunit.yml).