Boundaries & Conventions
This content is for v1.0. Switch to the latest version for up-to-date documentation.
Architectural boundaries
Section titled “Architectural boundaries”Deptrac enforces 12 layers. The dependency direction is one-way:
Commands → Migrations → Database → QueryBuilder → Repository →EntityManager → Schema → Attributes → Utils → Collection →Generators → Exceptionscomposer architecture:checkRun this after adding any cross-module dependency — Deptrac fails the build if a lower layer starts depending on a higher one.
Tech stack
Section titled “Tech stack”- Language: PHP 8.4+ (readonly properties, enums, fibers where appropriate)
- Databases: MySQL 8.0, PostgreSQL 15 — both must work for every SQL-touching change
- Mapping: PHP attributes only — no XML, no YAML, no annotations
- Testing: PHPUnit with real DB connections — no mocks
- QA: php-cs-fixer, PHPStan level 6, Deptrac, Infection mutation testing
Coding conventions
Section titled “Coding conventions”- Naming: Classes = PascalCase, methods/vars = camelCase, DB columns = snake_case via naming convention resolver.
- Types: Full type hints everywhere — no
mixedunless unavoidable, no@paramwhen the signature suffices. - Comments: none unless the why is non-obvious (hidden constraint, workaround, subtle invariant).
- Interfaces before implementations: depend on abstractions, not concrete classes.
- Exceptions: use types from
src/Exceptions/— never throw\Exceptiondirectly. - File size: keep classes focused; consider splitting past ~300 lines.
- No static state: zero static properties/methods that accumulate state across requests.
- Dual-DB: every SQL-touching feature must work on both MySQL and PostgreSQL — use
match($databaseName)in tests.
QA pipeline
Section titled “QA pipeline”composer cs:check # Dry-run php-cs-fixercomposer cs:fix # Apply CS fixescomposer static:check # PHPStan level 6composer architecture:check # Deptrac layer validationcomposer complexity:check # PHPMD cyclomatic/NPath analysiscomposer test # PHPUnit — MySQL + PostgreSQLcomposer test:mutation # Infection mutation testingcomposer qa # Full pipeline: CS → architecture → tests → mutationTests run inside the PHP container against both MySQL 8.0 and PostgreSQL 15 (#[DataProvider('databaseProvider')] runs each test on both):
docker compose up -d && docker compose exec php bashcomposer installcomposer test # all testscomposer test -- --filter=SomeTest # single classRead replicas
Section titled “Read replicas”No built-in read/write routing — intentional. Let infrastructure handle it (PgBouncer, ProxySQL, RDS Proxy), or use the per-context design described in Unit of Work & Identity Map.