How do you modernize a legacy PHP application?
You modernize a legacy PHP application incrementally: audit it, put a safety net around the flows that make money, move it to a supported PHP 8.x version, then grow a modern framework application beside the old code and move modules over one at a time behind the same URLs. AI features come on top once the core is stable. At every step the application keeps serving customers, and you can stop with a better system than you started with.
This is how we approach legacy work in our PHP development and Symfony development services. PHP is our core back-end language, and most legacy applications we see share the same symptoms: an old PHP version without security fixes, abandoned libraries, no tests, business logic mixed into templates, a deployment only one person understands, and a team afraid to change anything.
The plan in short:
- Audit (1 to 2 weeks)
- Safety net: monitoring, backups and tests on critical flows
- Supported PHP 8.x for the existing code
- Modern framework alongside the legacy code
- Move module by module behind the same URLs
- Retire the legacy code
- Add AI features on the stable core
Why not rewrite it from scratch?
A full rewrite is the most expensive way to modernize and the riskiest. It stops or slows feature work for months, it must rediscover business rules that live only in old code and in the heads of long-time users, and it switches everything on one day, which is when the forgotten rules surface as incidents.
| Approach | Business impact | Risk | When it fits |
|---|---|---|---|
| Full rewrite | Feature work frozen for months | High: lost rules, big-bang switch | Small apps, or code with nothing worth keeping |
| Incremental migration | Features continue in parallel | Low to medium: each step is small and reversible | Most applications that run a business |
| Upgrade only, no restructure | Minimal | Low | Code is reasonably structured but outdated |
| Do nothing | None today | Grows every month: security, hosting, hiring | Never a long-term option on unsupported PHP |
We default to incremental migration and say so openly. A rewrite is right only in narrow cases, and even then we prefer to run old and new side by side for a while.
What should a legacy PHP audit cover?
The audit decides the order of everything else, so it must be concrete. In 1 to 2 weeks we review:
- PHP version and extensions, and what breaks on the target version.
- Dependencies: which libraries are abandoned or pinned to old PHP, because these usually set the pace of the upgrade.
- Framework: none, a custom one, or an old Symfony, Laravel, Zend or CodeIgniter version.
- Database: schema, missing indexes, queries built from strings, and data quality problems.
- Security: injection risks, outdated authentication, secrets in code, file upload handling.
- Hosting and deployment: how code reaches production, backups, monitoring and who holds access.
- Business-critical flows: sign-up, checkout, billing, reports, imports, and which of them have any tests.
You get a written report with risks ranked by impact and a plan with a fixed quote for the next milestone.
Why do tests and monitoring come first?
Because every later step changes code nobody fully understands, and you need to know immediately when something breaks. Before touching the PHP version or the structure, we add:
- Error monitoring in production, so new errors after each release are visible within minutes.
- Backups and a tested restore, not just a backup job.
- Characterization tests on the flows that make money. These tests record what the application does today, right or wrong, so a change in behavior is caught before customers see it.
- Repeatable deployment through CI, so any engineer can release and roll back.
Static analysis with PHPStan starts here too, at a low level, raised step by step as the code improves.
What is the PHP 8.x upgrade path?
The upgrade path is to move the existing code, unchanged in structure, to a supported PHP 8.x version first, so security fixes flow again and modern tooling works. PHP 7.x, 8.0 and 8.1 no longer receive security fixes, and PHP 8.2 is in its last year of security support.
| Starting point | Typical path | Main obstacles |
|---|---|---|
| PHP 5.x | Through PHP 7.4 compatibility to a current PHP 8 release | Removed functions and extensions, old database drivers, abandoned libraries |
| PHP 7.0 to 7.3 | Straight to a current PHP 8 release with automated refactoring | Changed comparisons, stricter errors, library updates |
| PHP 7.4 to 8.1 | Current PHP 8 release | Deprecations, library and framework versions |
| PHP 8.2 | Current PHP 8 release before the end of 2026 | Usually small; plan it now |
The steps: static analysis against the target version to list incompatibilities; update or replace libraries; Rector for mechanical changes such as deprecated functions and signatures; manual review of the rest, especially string and number comparisons and error handling; then staging under the new version and a staged release with monitoring. For a typical business application this takes 3 to 12 weeks.
How does the strangler pattern work in PHP?
The strangler pattern means a new application grows around the old one and gradually takes over its routes until the old code can be switched off. In PHP it is practical because both applications can share the same server, database and session.
How we set it up:
- One entry point. Requests go first to a new Symfony application. If it has a route for the URL, it answers; if not, it hands the request to the legacy code, which runs as before.
- Shared data. Both applications use the same database at first. New code accesses it through Doctrine entities mapped to the existing tables, so no data migration is needed on day one.
- Shared session and login, so users never notice which side served a page.
- New features only in the new application, from the first day.
- Module by module. Old pages and endpoints move over one at a time, each with tests before the switch, behind the same URLs.
- Retire each legacy module when traffic shows nothing uses it any more.
This spreads cost across releases and keeps the business running. The team ships features throughout, and at any point the system is better than before.
Which framework should the new code use?
For long-lived business systems we use Symfony, our default framework: explicit architecture, Doctrine's separation of domain from database, long-term support releases and predictable upgrades. Those are exactly the properties a team needs after years of legacy pain. Ritoria, a Symfony platform we built with 54 domain entities, ran in production on AWS for two and a half years through 292 commits and 120 database migrations of continuous change, which is the kind of steady evolution a modernized system should support.
If your team already works in Laravel, migrating to Laravel is a valid path, and we work in it through our Laravel development service. If the legacy code already runs an old Symfony version, the plan becomes a Symfony upgrade, one major version at a time. Our comparison of Symfony vs Laravel for SaaS explains the trade-offs.
How do you add AI to a modernized PHP application?
Once the core runs on supported PHP with tests, AI features are built as normal services and background jobs that call the OpenAI or Anthropic Claude APIs, so they follow the same permissions, logging and tests as the rest of the code. Typical first features are drafting and summarizing, search and answers over your own documents with RAG, and agents that act through your existing business logic with human approval for anything involving money or customer communication.
When a feature needs heavy data processing or custom models, we add a separate Python service that the PHP application calls through an API, instead of moving the product to a new language. Our own product AI Resume Master is built this way: PHP and Symfony for the product, React for the interface and Python for AI generation, and it reached 50,000 monthly active users. More on the approach is on our AI integration page.
What does legacy PHP modernization cost?
The cost depends on what the audit finds: the version gap, the dependency list, test coverage and how much logic is tangled together. That is why we quote modernization after the audit, with a fixed price for each milestone, instead of guessing in advance.
| Phase | Typical timeline | How it is priced with us |
|---|---|---|
| Audit with written report and plan | 1 to 2 weeks | Part of the first milestone |
| Safety net and PHP 8.x upgrade | 3 to 12 weeks | Fixed quote after the audit |
| Module-by-module migration | Months, alongside features | Fixed milestones or a dedicated team budget |
| AI feature on the modernized core | 3 to 8 weeks | From $10,000 |
Our minimum project size is $10,000. If you plan ongoing modernization in parallel with your roadmap, a dedicated development team on a monthly budget is often the simplest model.
Our verdict and how we start
Do not rewrite by default. Reach a supported PHP version, put tests around what makes money, and move to a modern framework module by module while the business keeps running. Add AI on a stable core. We start with a short call and an audit that ends with a written report and a plan. See our PHP development and Symfony development services, or contact us and tell us your current PHP version and what is not working.