Replacing old PHP one piece at a time
Why rewrites fail and increments work
A full rewrite asks the business to wait a long time for a system that does what the old one already does, while paying to keep the old one alive. Requirements keep changing in the meantime, and hidden rules surface late. Incremental modernization delivers working software continuously. At every point there is one production system, part old and part new, and the project can be paused after any stage with the gains already banked.
Capture behavior before touching it
Legacy code has no specification except itself. So the first job is characterization testing: we record real requests and the responses, database changes and files they produce, then replay them automatically. For calculation-heavy code we feed in a large sample of historical records and store the results. These tests do not judge whether the behavior is correct. They only tell us when it changes, which is exactly the safety net refactoring needs. Bugs we discover are listed for you to decide on, and not silently fixed.
Lay the foundations inside the old code
Next come changes that make the old code easier to work with and alter no behavior. Composer is introduced and an autoloader takes over from include chains. All requests are funneled through a single front controller. Configuration and credentials move out of scattered files. Calls to the removed mysql extension are replaced with PDO and prepared statements behind a small database class. Global variables and superglobals are pushed to the edges. Static analysis and automated refactoring tools do much of the repetitive work, with the characterization tests confirming nothing shifted.
Extract the rules, then strangle the rest
With the ground stable, we pull business logic out of page scripts into service classes: pricing, eligibility, stock allocation, whatever makes your system yours. Those classes are plain PHP and work under any framework. Then a CodeIgniter 4 or Laravel application is placed in front. The web server or the new router sends each URL either to new controllers or to the legacy front controller. Both share the session and the database. Feature by feature, routes move across. CodeIgniter 4 suits teams that want to stay light. Laravel suits products heading toward queues, billing and larger teams.
Keeping the business running meanwhile
Releases are small and frequent, each one reversible. Urgent fixes to the old code continue throughout and are covered by the same tests. We agree the order of work with you by business risk and pain, not by technical neatness. If the legacy system happens to be a CodeIgniter 3 application in reasonable shape, a direct CodeIgniter 3 to 4 upgrade may be shorter than this route, and we will tell you so. For the wider picture across platforms, see migration and modernization.