So I've been doing something dumb and was getting away with it. Namely, I've been hacking on esgeroth.org directly in production.
Alas, I finally flew too close to the sun. I'd been working on the structural goals I set for my website and while doing so discovered that __autoload has been deprecated (and removed in PHP 8). So I started down the rabbit hole of how modern PHP does autoloading and found this nice group called the PHP Framework Interop Group and they have a number of recommendations (PSRs - PHP Standards Recommendations) and PSR-4 is all about autoloading. Great!
So about a month or so ago I set out to redo my autoloading in a PSR-4 compliant manner. This in turn involved moving a dozen or so files around (I wasn't actually using too many classes, esgeroth.org uses very old school PHP). Then (I thought) I fixed up all the relative file paths in those files and manually tested (I thought) all the impacted pages and then went to bed.
The next morning I heard from both Jeff and Branden that the esgeroth.org apache logs were filling up the logging partition on our server. It turns out I missed one relative path and I had a bug in my code processing that path that led to an infinite loop that generated an error in the apache error log each time through the loop. And I missed testing the page using that code path. But at least one crawler had decided to crawl that page and thus find this bug for me.
The issue was quickly fixed, but the embarrassment really took the wind out of my sails for a while. But then I decided that the best way to make sure that doesn't happen again is probably also the best way to make sure Pete's Log is ready for the next 20+ years: make sure that I'm doing the automated testing before web crawlers can do it for me.
So for the second time in its history (and more than a decade since the first time) I spun up a dev server for esgeroth.org. And I set up phpunit, phpstan and PHP CodeSniffer. And I started refactoring and writing unit tests while doing so. And I'm not deploying again until all those tests come back clean and I achieve some minimum percentage of test coverage.
So the old esgeroth.org was very much rooted in the PHP of 20+ years ago. Not very many classes, code and HTML intermixed. This does not lend itself very well to unit testing. So to make it testable, I'm refactoring into modern object oriented PHP.
I tried once to use a PHP MVC framework, but that didn't end well. This time I have the advantage of having now done a lot of MVC (although in ASP.NET). But I also know I don't want another third-party framework. So I have spent much of my free time these past few weeks hacking together my own PHP MVC-ish infrastructure.
Today I coded up my own dependency injection container. I based it on the PSR 11 container interface, meaning I should be able to exchange it for an external library if the need ever arises.
It was easier than expected and quite fun. Take the class you want to instantiate, use reflection to get its constructor, see which classes it wants passed into it, recursively build those the same way until hopefully you eventually get to a class with no constructor arguments. Only about 60 lines of code.
With that in place, I'm starting to feel like an end is maybe in sight. What's mostly left now is the grunt work of converting each remaining page - extract the logic into a controller method and the presentation into a view template. Glue it together. Maybe write some tests. Repeat.
We'll see how much longer it takes me to get there. I'm excited about it. But I'm also ready to be done and move on to other things.