PHP Database Layer Refactoring & Modernisation

The database layer is often the most neglected part of a legacy PHP application — and the riskiest to change. Raw SQL scattered across service classes, un-normalised schemas that have grown organically for a decade, no migration tooling, no ORM. We modernise it safely using Indoctrinate — our open-source tool for synchronising your database with Doctrine specifications — alongside the full incremental migration process.

What makes legacy PHP database layers hard to change

  • Raw SQL queries spread across dozens of files with no central abstraction
  • Schema changes happen in production with no migration history
  • Tables with hundreds of columns, many unused or duplicated
  • Business logic embedded directly in stored procedures or triggers
  • No indexes, no foreign key constraints, referential integrity enforced only in PHP
  • Active Record patterns that couple domain objects tightly to DB schema

Indoctrinate: automated schema analysis & fixing

Indoctrinate is an open-source tool we built and maintain to automate the schema side of database refactoring. It analyses your live database against Doctrine specifications, surfaces inconsistencies, and applies fixes automatically — so Doctrine entity mappings don't fail on structural problems that could have been caught in advance.

$ composer require kerrialn/indoctrinate
$ php bin/indoctrinate fix --dry
$ php bin/indoctrinate fix --log=var/log/indoctrinate

The --dry flag previews every change without applying it — the same safe-first approach we use with Rector.

How we refactor the database layer

Schema analysis with Indoctrinate

We run Indoctrinate's dry-run mode against your live database to get a complete picture: missing auto-increment primary keys, column-to-type mismatches, constraint gaps, normalisation violations, and tables that diverge from Doctrine's expectations. This is the starting inventory — the prioritised schema remediation plan that shapes all subsequent work.

Query inventory and consolidation

We locate every raw SQL query in your codebase, group them by the table or concept they operate on, and identify which can be consolidated behind a repository interface. This gives us the abstraction target before writing a single line of ORM mapping.

Incremental ORM introduction

We introduce ORM mappings (typically Doctrine) alongside existing raw queries using a dual-path approach. Both paths run simultaneously, results are compared, and the raw query is removed only after the ORM version is verified to be producing identical results. No cutover risk.

Schema migration with rollback safety

Schema changes are applied using reversible migrations: every ALTER TABLE has a matching rollback, columns are never dropped until the code reading them has been removed and verified, and we use expand-contract patterns for zero-downtime changes on live traffic. Indoctrinate is re-run after each batch to verify the schema remains Doctrine-consistent.

View and stored procedure migration

Database views and stored procedures that contain business logic are migrated into the application layer — PHP services with proper test coverage — where they can be maintained, versioned, and upgraded with tools like Rector.

Technologies we work with

  • Indoctrinate: automated schema analysis and Doctrine synchronisation
  • MySQL / MariaDB schema analysis and migration
  • PostgreSQL modernisation
  • Doctrine ORM mapping and query builder migration
  • Doctrine Migrations for versioned schema changes
  • Propel to Doctrine migration
  • Active Record (Eloquent, CakePHP) to repository pattern
  • View/stored procedure logic extraction to PHP