Legacy PHP to Laravel: Rebuilding the System a Transportation Company Runs On

Legacy PHP to Laravel: Rebuilding the System a Transportation Company Runs On

June 11, 2026

The system behind the business

A transportation company runs on its software in a way that is easy to underestimate from the outside. Trucks need to be assigned. Drivers need to be scheduled and tracked. Dispatch decisions happen continuously. Compliance has to be maintained. Operations do not pause, and the software that coordinates all of it is not a convenience. It is the business.

Our client ran all of this through a PHP application built years earlier. It worked, in the sense that the business ran on it every day. But it had reached the state that aging PHP applications reach: every change was risky, every new feature took too long, and the people who understood the codebase were a constraint on everything.

The decision to migrate was not driven by the application failing. It was driven by the application becoming an obstacle to the business growing.

What the old application actually looked like

The codebase had the signature of PHP applications from an earlier era, built quickly to meet immediate needs and extended over years without architectural discipline.

Routing logic was mixed with rendering. The code that decided what to do with a request and the code that produced the HTML response were the same code, interleaved in the same files. There was no clean separation between handling a request and displaying a result.

SQL was distributed through the page files. Database queries lived wherever they were needed, embedded directly in the files that used them, often built by concatenating strings. There was no data access layer. The same query logic was frequently duplicated across multiple files because there was no central place to put it.

There was no test coverage. None. Every change was verified by manually clicking through the application and hoping nothing else broke. For a system running live operations, this meant every deployment carried real risk.

And the structural problem underneath all of it: making any change safely required understanding the whole system, because the system had no boundaries. A change to one feature could break another feature in a way that no one would predict, because everything was connected to everything and nothing was isolated.

This is the actual cost of an unarchitected codebase. Not that it runs badly, but that it cannot be changed safely or quickly, which means the business it supports cannot move quickly either.

What we migrated to

We rebuilt the application on Laravel with a properly layered architecture. Laravel is a mature, widely-used PHP framework, which mattered for a specific reason: the client’s system is in PHP, their future developers will be PHP developers, and Laravel is where the modern PHP ecosystem and talent pool are. Migrating to Laravel kept them in a language and ecosystem they could staff, while giving them the architecture they did not have before.

The architecture is the substance of what changed.

Clean separation between data access, business logic, and presentation. Database access now lives in a defined data layer, not scattered through page files. Business logic, the rules about how trucks get assigned, how schedules get built, how compliance gets tracked, lives in a service layer that can be understood and tested on its own. Presentation is separate from both. A developer can now reason about one layer without holding the entire system in their head.

A tested service layer. The business logic that the company depends on is now covered by tests. A change to the scheduling logic can be verified automatically rather than by manual clicking and hoping. This single fact changes the risk profile of every future change.

A structure any PHP developer can navigate. The new codebase follows Laravel’s conventions, which are widely understood. A PHP developer who has never seen this specific application can open it and understand how it is organized, because it is organized the way modern Laravel applications are organized. The client is no longer dependent on the few people who understood the old codebase’s idiosyncrasies.

Preserving the logic that mattered

The most important discipline in this migration was the one that does not show up in the architecture diagram.

The operational logic the business depended on, the scheduling rules, the driver assignment logic, the compliance tracking, was preserved and validated, not reinvented. This is the difference between a migration that succeeds and one that creates months of subtle problems.

An aging system like this encodes years of accumulated business rules, many of them undocumented, many of them existing because of a specific real-world situation that came up once and got handled. Some of those rules look arbitrary until you understand the operational reality behind them. The temptation in a rewrite is to treat the old system’s behavior as a rough guide and rebuild based on what the rules “should” be. That temptation is how rewrites break businesses.

We treated the old system’s actual behavior as the specification. We extracted the business rules, validated them against how the operation actually works, and reproduced them in the new architecture. Where a rule looked strange, we asked why before changing it, rather than assuming it was a mistake. Some strange-looking rules turned out to encode real operational requirements. Others turned out to be genuine bugs that had been quietly causing problems, which we then fixed deliberately rather than carrying forward.

What the company got

The headline outcome is simple to state and significant in practice: the company now ships changes in days that previously took weeks.

That speed does not come from the framework being faster to write. It comes from the architecture. When the system has clean boundaries, a change to one feature does not require understanding the whole system, because the change is isolated to the layer and the module it belongs to. A developer can make a change, see exactly what it affects, verify it with tests, and deploy it with confidence. The understanding-the-whole-system tax that the old codebase charged on every change is gone.

That is what good architecture actually buys. It is invisible right up until you have it, and then it is the difference between a business that can adapt its operations quickly and one that waits weeks for every change to its core system.

The other outcomes follow from the same foundation. New developers can be onboarded without months of learning the old system’s quirks. New features can be added without the risk that they will break something unrelated. The business logic is documented and tested rather than living only in code and in a few people’s memory.

How AI fit into the project

AI assistance compressed the parts of this migration that are time-consuming but do not require architectural judgment.

In the analysis phase, AI helped map the old codebase: tracing where SQL lived, identifying duplicated logic across files, and surfacing the business rules embedded in the page files. This is the archaeology that used to consume the most time in a PHP migration, reading through years of accumulated code to understand what it actually does. AI made that phase substantially faster.

In the build phase, AI assisted in generating the Laravel structure, the data layer scaffolding, and first-draft implementations of the extracted business logic. Engineers made the architectural decisions, validated the business rules, and hardened the code. The judgment stayed human. The mechanical work got faster.

In testing, AI generated the initial test coverage for the business logic, which engineers then extended to cover the edge cases that matter for a live operational system.

What AI did not do was decide how the system should be architected, determine which business rules were real and which were bugs, or validate that the new system behaved correctly for the operation. Those decisions required understanding the business, and that remained the work of the engineering team in collaboration with the client.

The lesson that generalizes

This project is a clear example of a pattern that holds across most legacy modernization.

The framework you migrate to matters less than the architecture you migrate into. Moving from old PHP to Laravel is valuable, but the value is not in the framework name. It is in the clean separation of concerns, the tested business logic, and the structure that lets the system be changed safely. You could get most of that value with a different modern framework. You could fail to get it even with Laravel if you carried the old architecture forward unchanged.

For any organization running a business-critical system on an unarchitected codebase, the real cost is not that the system runs poorly. It usually runs fine. The real cost is that the system cannot change at the speed the business needs, because every change requires understanding everything and risks breaking anything. Modernization, done properly, removes that constraint. That is the outcome worth paying for.

Is a legacy PHP app slowing your business down?

We migrate business-critical PHP systems to Laravel with layered, tested architecture — preserving the business rules that matter and removing the change-is-risky tax.

The framework matters less than the architecture. That's where we start.

Discuss your migration

A technical conversation, not a sales pitch.