AGENTS
August 7, 2026 · View on GitHub
Read root AGENTS.md first. Security: SECURITY.md.
Purpose
Schema (and rare seed) changes as timestamped SQL files, applied by php runway migrate.
Driver comes from database.driver in config (overridable by DB_DRIVER in .env). The migrator applies only files for that driver.
Conventions
- Filename by driver:
- SQLite (default):
YYYYMMDDHHMMSS_description.sql - MySQL:
YYYYMMDDHHMMSS_description.mysql.sql - Prefer the same timestamp prefix for a paired change so humans can match SQLite ↔ MySQL files.
- SQLite (default):
- Directory: project root
migrations/only. - Tracking table:
_migrations(name,applied_at) — DDL is driver-specific insideMigrateCommand. - Idempotency: command skips already-applied names; still write SQL that is safe to reason about (
CREATE TABLE IF NOT EXISTSwhere appropriate). - Do not put MySQL SQL in plain
.sqlfiles (or SQLite SQL in*.mysql.sql). Glob would match both; the command filters by suffix. - Multi-statement: migrate splits on statement boundaries; keep statements clear; line
--comments are stripped. - App models must match tables after migrate (e.g.
posts↔App\Model\Post). - Do not put secrets or production data dumps in migrations committed to git.
Workflow
# SQLite (default): add migrations/20260315120000_add_widgets.sql
# MySQL: add migrations/20260315120000_add_widgets.mysql.sql
php runway migrate
Do not
- Run arbitrary user input as SQL through the migrator.
- Invent a second migration tool (Phinx, Doctrine Migrations) unless the project consciously adopts it and removes this one.
- Edit an already-applied migration that has shipped to others — add a new file instead.
- Rely on “mostly portable” SQL shared across drivers — ship paired files instead.