DVHARDWARE - How Codex Helped Me Modernize a 24-Year-Old PHP Codebase

Posted on by


There are moments when technology quietly changes the rules of the game.

Not with a dramatic announcement or a futuristic robot, but with a realization that makes you stop what you are doing and think: well... that's different. You can just... build things.

For me, that was a central thought when I pointed an AI coding agent at a 24-year-old PHP codebase that I had been avoiding for years.

DVHARDWARE began life in 2002 as a PHP-Nuke installation. Over the years, it survived security incidents, multiple PHP upgrades, countless hacky customizations, and an embarrassing amount of technical debt. Rewriting it always felt like one of those projects that would consume months of evenings and weekends before producing anything useful.

Instead, it took a few evenings.

Not because AI magically wrote perfect software- it absolutely did not- but because it completely changed the economics of tackling legacy code. Suddenly, the hard part was no longer writing the code. It was deciding what the code should become, reviewing thousands of generated lines, and steering AI agents that never seemed to get tired.

This is the story of how a 2002-era PHP website became a modern PHP 8.5 application, what AI did surprisingly well, what it got wrong, and what this means for DVHARDWARE.

Migrating DVH with Codex

 

Legacy from 2002

It is surprising the site still ran as well as it did.

DVHARDWARE originated as PHP-Nuke 5.4 website, a 2002-era content management system designed during the PHP 4 days. With my limited knowledge of PHP at the time, I customized the website to match my needs. The side effect was that upgrades became nearly impossible.

Newer versions of PHP-Nuke were released over the years, but upgrading meant porting all my customizations to every new version. Basically, it was a ton of work every time and became impossible over time.

Over the years, the site suffered several security incidents, which were sometimes dealt with in creative ways. Eventually, some code migrations became mandatory as the site had to move to newer versions of PHP. Web hosts don't like running severely outdated PHP versions, duh. More recently, ChatGPT helped me get the site compatible with PHP 7 and PHP 8.

Looking back, it is remarkable how well the nearly 25-year-old codebase held up. With some minor work, it just kept running like the Duracell Bunny.

But in the back of my mind, I always wanted to ensure that it could last another 25 years.

Fast-forward to 2026, and we are now in the agentic AI era. Code is cheap, and I wanted to see whether I could take my experience from the Java world and perform a full rewrite of a CMS in a language in which I had never done serious development.

The last major work on DVHARDWARE was a new theme in 2021. Back then, it took a couple of weeks to give the entire website a mobile-compatible Bootstrap theme.The internals, however, were still early-2000s PHP code with a ton of hacky implementations. Migrating that to a new version was a whole different ball park.

Typically, every request to the web server went to a specific PHP file. Those files relied on a couple of globally shared main files. There was no separation of concerns, and many files handled everything from database access to HTML rendering.

Oh, and everything lived in a publicly accessible folder, uploaded via FTP rather than through a Git-triggered deployment workflow.

Getting to work with Codex

After deliberating between Claude Code and Codex, I picked OpenAI's Codex because of reports that it would last longer within my intended budget.

First, I downloaded the entire codebase to my PC, placed it under Git version control, and did some manual cleanup. The site had accumulated a lot of dead code over the years. That process took about one evening: exploring what was there, deciding what was no longer needed, and making some minor preparations.

The next day, I paid for a €23-per-month ChatGPT Plus subscription and got to work.

My knowledge of modern PHP was limited, so I did not really know what was possible with PHP 8.5. PHP has matured significantly, although I was surprised that features taken for granted in many other languages arrived relatively recently. Enums, for example, were not added until late 2021.

After several sparring sessions with the LLM, we drafted a plan of around ten steps for the initial migration from the original procedural PHP code to a layered architecture.

Looking back, I should have spent more time on this phase. Better architectural boundaries at the start might have prevented some later refactoring. But I was also surprised by how quickly Codex churned through the original plan. It just ploughed its way through the codebase and figured out a lot of stuff on its own.

I noticed that LLMs are extremely bad at estimating how long a task will take. They seem to use a human frame of reference. That can be a problem because the model may dismiss a path as "taking too long" even though it can complete the work in ten minutes.

The first two phases of the migration plan were described as a "two-week step." They were completed and validated in less than three hours.

The first practical step was getting the site to run locally in a Docker container with a copy of the production database. This gave Codex room to find its way around the application. It could run commands, install dependencies, execute the site locally, perform automated checks, and verify its own work.

I gave the model a lot of freedom to see what it would do, and I was often surprised by the effort it put in. It did not simply start migrating code. Without being told explicitly, it first created an inventory of what needed to happen. It even wrote a shell script containing several smoke tests, allowing it to check quickly whether anything important had broken after each migration phase.

It's fast. Very fast.

After just three evenings, I had an initial version that reached feature parity with the existing website. It even included some bug fixes and improvements over the original.

I already use AI extensively at work, but the speed still surprised me. Codex felt like a major step up from the Copilot tooling I use professionally.

Using a strangler fig migration pattern, I had a PHP 8.5 version of DVHARDWARE running alongside the original codebase. Every active feature was ported, and we even created a new and improved admin area.

It is slightly amusing that the old admin area was still using a theme from 2002 or 2003. When I redesigned the public site in 2021, I could not justify spending more time upgrading an interface that only I would see. Now, the whole thing was migrated in no time.

Before the experiment, I expected Codex to get me perhaps 80 or 90 percent of the way. I assumed I would then need to find and explain numerous bugs.

That was not what happened. That tedious phase did not occur.

I encountered bugs after certain phases and refactors, but nothing major. Then again, DVHARDWARE is a relatively straightforward content management system. Much of the functionality consists of basic CRUD operations: creating, reading, updating, and deleting data.

As a vibe coder, I could probably have stopped after the ten-step migration. Everything worked, and after a thorough testing session, it would likely have been ready for production.

But as a software developer, I was not satisfied yet.

A look at the codebase revealed plenty of things I did not like. I also still had more than three weeks left on my Codex subscription, which meant there were plenty of tokens left to burn.

From working software to better software

I decided to take the project further and improve the code quality.

During those first three days, I discovered that modern PHP can feel surprisingly similar to a Spring Boot application from the Java world. PHP is different, of course, but many of the concepts felt familiar.

Initially, I wanted to avoid using a framework to keep the application free of unnecessary bloat. Eventually, I settled on using selected Symfony components. They are battle-tested, and they simplified parts of the codebase without requiring me to turn the entire site into a Symfony application.

The biggest lesson was that I should have invested more effort in the initial plan. Defining stronger boundaries first might have produced a cleaner initial result, although it probably would also have made the first migration slower.

When I examined the generated code more closely, I noticed that the LLM had often copied assumptions from the legacy implementation without questioning them. Some of those legacy artifacts no longer made sense.

In one case, it added an extra guard so a poll would only be displayed if it contained more than one answer option. Ridiculous, because validation in the admin area already prevented an invalid poll from being created. This is still one of the areas where judgment is needed; the latest frontier AI models are very strong but tend to overengineer much of your code to a degree a human would never do. Newer models like GPT 5.6 Sol tend to overengineer things that should remain a lot simpler.

Despite these issues, the initial migration was impressive and contained very few bugs. Codex generally understood the essence of what needed to happen.

Intelligent, but sometimes very dumb

Then there were moments when it did remarkably stupid things.

At one point, there was a bug in my "who's online" component. Instead of finding the root cause, Codex "fixed" the problem by inserting getUserCount() + 1 somewhere in the code so the displayed text would meet the expectation.

Technically, the number on the screen was now correct. But it totally missed the point. The same model that had produced impressive work fifteen minutes earlier suddenly felt extremely dumb. And this is a common theme with AI in my experience. You see wild swings in both directions.

When I zoomed out and examined the general flow of data through the application, I found more things I did not like. Database layers were still calculating and manipulating data specifically for presentation in the templates. It worked, but there was no clean enough separation of concerns. 

After the initial version, I spent several more evenings refactoring the application. The goal was partly to improve the architecture and partly to continue the experiment.

I explored PHPStan, a static analysis tool for PHP codebases. As the refactoring progressed, it became easier to reach higher PHPStan levels without adding too much ceremony. Eventually, I settled on PHPStan level 9.

At one point, I also asked an agent to draft a plan for simplifying the codebase. Some of its suggestions were bogus, but most of the plan made sense. Following it resulted in hundreds of lines of code being deleted.

Some of those lines were artifacts from intermediate refactoring steps. A mapper or translation layer that made sense during one phase, but became redundant a few phases later. I saw this pattern various times during the migration. AI tends to work in an additive way, and rarely starts refactoring like a human. You really need to force it.

During this work, I also moved toward a more Onion-style layered architecture. Dependency boundaries are now enforced with Deptrac, a static analysis tool that verifies architectural rules in PHP projects.

The review bottleneck

The speed of AI agents is also one of their disadvantages.

For a human, it is difficult to review all the generated code. After a while, the volume starts to lull you to sleep.

I reviewed some of the more technical changes in depth. But when the model worked on views, templates, or straightforward mappers, my reaction was often: "Looks good to me, I'll just test it."

Then I rubber-stamped the change without verifying every individual line.

After a while, you begin to trust the model a little too much. That is probably one of the biggest risks of AI-assisted software development. The code arrives faster than a human can maintain the same level of attention.

I was impressed by how well Codex hides the model's context-window limitations. It was able to keep working across a sprawling codebase without constantly exposing context management to me. OpenAI has done a good job with this.

Adversarial reviews using a model from a different vendor also work extremely well. For this experiment, I did not want to pay for two AI services, so I limited myself to copying Codex output into the free version of Claude. In many cases, this helped improve the result and catch issues that the first model had missed. 

Who are we writing code for?

I do wonder what the future of programming will look like.

Many subjective standards around code quality were created with humans in mind. We organize software so people can understand it, review it, and work together efficiently.

But will all of those standards remain equally important one, two, or five years from now?

I do not know.

It sometimes feels as though we are still writing software under the assumption that AI will disappear one day and all code will again be written entirely by hand. LLMs are already much faster than humans at interpreting large codebases, and given the right context, they're often better at it than someone unfamiliar with the codebase.

Documentation is also one of the things I'm unsure about. Generating documentation is very cheap now, within a couple of minutes an agent will happily produce hundreds of lines of documentation. On one hand, I think these files can be of good use. Especially if they document important architectural decisions, implementation details, and trade-offs.

The audience for technical documentation may no longer be exclusively human. In fact, it no longer is. But it quickly becomes too much if each new user story adds yet another markdown file. Documentation needs to be maintained so it does not get out-of-date and doesn't become a trash folder -- and that burns a lot of tokens and time.

Usage limits -- the main limitation

Overall, the DVHARDWARE migration matches my professional experience: AI agents are extremely capable.

In just a few days, I modernized a codebase written in a language I knew relatively little about. Granted, it was a self-contained project with mostly straightforward CRUD functionality. Still, it demonstrates that deep knowledge of a specific language or framework no longer has to be a hard blocker in the AI era. You can just do things.

Before AI, this project would probably have consumed many evenings spread over several months.

The biggest practical problem I encountered during the migration was OpenAI's usage limits. On my plan, I could typically code intensively for only about two evenings before hitting the weekly limit. Moving at full speed would have required the €103-per-month plan, and possibly more.

Fortunately, OpenAI reset the weekly quota several times during the period in which I used Codex, either to mark certain milestones or to compensate for an outage. That eased the pain somewhat. But counting on random resets would not be a good strategy if you're on a deadline.

The result

The new site was deployed two weeks ago with various improvements in the public-facing areas, as well as enhancements in the admin area. I have reduced much of the friction involved in adding and managing content. I expect that this will make DVHARDWARE more active again. 

Most of the heavy lifting of the migration was completed using GPT 5.5 and GPT 5.6 Sol at the "medium" reasoning level. Since then, OpenAI has made improvements that made GPT 5.6 Luna significantly cheaper to run. I started using Luna with the "Extra High" reasoning level two weeks ago. It is somewhat slower at that setting, but for a lot of tasks it performs well. Suddenly, my 23EUR plan lasted days longer. However, my initial enthusiasm about Luna has dampened somewhat. After working with it for a couple of days, I found the only reason I'm using it was to try to conserve quota. For analysis and architectural reviews, you really want 5.6 Sol on a higher reasoning level.

I could have stopped at day three or four, after completing my initial goal, but I just kept going as it was quite a blast to fire up Codex to do more and more. Here's a wrap-up of everything I did;

  • Put DVHARDWARE under version control in a Git repository and made it run locally via Docker containers (no more WampServer like in the old days!)
  • Migrated the codebase to a hexagonal-inspired modern architecture. Clean boundaries, no more giant PHP files that do everything from getting data from the database to rendering HTML.
  • Enforced PHPStan level 9 to improve code quality, plus implemented Deptrac to enforce architectural rules
  • Enhanced the search functionality
  • Better security
  • Improved pagination
  • Breadcrumbs for easier navigation
  • Fixed bugs in the poll functionality
  • Enhanced the RSS feed functionality
  • Endless refactors... By default, AI-generated code does not focus on reducing complexity or cleaning up intermediary code. 
  • Massive overhaul for the admin zone. Biggest changes include the addition of a rich text editor and image upload functionality. Before this, everything was done by manually inputting HTML and uploading files via FTP... 
  • Automated some frequently performed actions
  • Changed the URL scheme to use slugs, while ensuring all important legacy links keep functioning via redirects. 
  • Made Lighthouse optimizations, improving the site rendering speed metrics. It just feels snappier too.

One feature I initially removed was comments.

For many years, DVHARDWARE used Disqus. It was a major improvement over the site's original comment system when I adopted it around 2012. At the time, it solved many of the problems I had with spam accounts and spam comments.

Later, Disqus moved to a freemium model that injected far too many advertisements into DVHARDWARE. The solution was to let Codex cook up a new comments system. At first, I explored the integration of ready-made solutions. A lot of them seemed promising, but given the limits of my webhost, the requirements I had in mind, and the low volume of comments, I decided to just hand-roll a threaded comments system with anonymous posting

 Overall, this involved about two evenings' worth of work to design it, implement it, verify it, and improve it to get it production-ready. Plus Codex also cooked up scripts to migrate all legacy comments. Not just the old PHP-Nuke comments but also everything from a Disqus export.

DVH new architecture

So... how much would this cost with API-based pricing?

I asked Codex to calculate how much my AI consumption would cost on API pricing; after working for four minutes, the model estimated it around $1,306. Definitely insane how large the difference is between the subscriptions and the usage-based billing.

Conclusion

The migration began as an experiment: what would happen if I pointed an AI coding agent at a 24-year-old PHP codebase that I had avoided rewriting for years?

A few evenings later, I had my answer.

DVHARDWARE went from an old procedural PHP site maintained via FTP uploads to a modern PHP 8.5 application with version control, automated checks, architectural boundaries, and a proper deployment workflow.

AI did not remove the need for software engineering. In some ways, it made engineering judgment more important. The model could write, migrate, and refactor code at remarkable speed, but it still needed someone to define the destination, question inherited assumptions, recognize bad shortcuts, and decide when working software was not yet good enough.

Two years ago, I probably would not have started this project.

Now the codebase is modernized, the site is easier to maintain, and I am still thinking about what to improve next.

That is the part that feels different.

 

[ Back to Articles ]

Thanks. Your comment is waiting for moderation.
Your comment was published.

Comments (0)

No comments yet.

Leave a comment

Replying to