Any PHP coders out there?
So PHP really did it in 8.0: They really made accessing undefined vars *and* array indices a full warning rather than a notice. I had written in past newsletters that I hoped this didn't mean what it sounded like it meant.
But it does.
They really did it.
https://wiki.php.net/rfc/engine_warnings
I finally had to face the music with the upgraded MUUG server which now uses PHP8. It was coming for me in Fedora 25 anyhow (maybe 4 more months to postpone that change). The MUUG server is about 80% code that Allan Pollard wrote (thanks Allan!) and 20% my own code. Neither wrote according to PHP8's magic new requirements.
Anyone here who does PHP and hasn't treated it as a typed / declared language, because it is not one, is in for a great deal of pain when they are forced to upgrade to PHP 8. I'm not sure I've ever come across existing PHP code where the dev treated it as a language where you must pre-declare everything. Of course, such people must exist, as exhibited by the voting record for this PHP RFC. Perhaps they are people who only recently took up PHP and/or are coming from stricter languages.
And that is my main beef: if you want a strict language, use a strict language. Why take a loose language, which has always been loose and is loose by design, and suddenly make a major change that is going to spew out errors all over everyone's screen (if display_errors is on) for 90% of all legacy code? If I want strict variable declaration, I'll use one of the zillion languages that force you, and even do nice compile-time checks for you.
And you just know that while, at the moment, this change is limited to making it a warning, the tyrants are itching to make this a full explosion error. You can see it in the voting ("Change undefined variable severity to?": vote 36 to 28). Luckily for us PHP requires a 2/3 majority to pass an RFC.
To "fix" these errors in code, you can in most cases use a lot of tricks, like massive use of ?? everywhere. But that makes the code look really ugly and I start to question why? And if you use list() to capture results of a function which can return variable type of variable length arrays, you're really in trouble as there's no current syntax to combine ?? or isset() with that.
Sure, you can go in and turn your PHP into C by pre-declaring every variable, if you can spot them all in complex functions or global scope code. But that only helps you with the "undefined variables" thing, not the "undefined array index" thing. The latter is far more insidious because your index can be a variable itself! So for that case you must always use isset() or ?? or some other trick.
I could go into more examples of what I had to do to the MUUG code if anyone is interested.
So what can you do in the real world? The first thing you do is turn off display_errors, which is probably off on production boxes anyhow (but wasn't on "hobby" boxes like MUUG, but it is now). Then make sure those warnings are being logged. Then sit back and let people use your site and wait for the MBs of log lines saying undefined this and that.
Then you have a choice: a) ignore it all and set your logrotate to a short period of time so you don't fill your log disks; or b) fix every error that shows up. I did (b) on MUUG and it's not fun, and that's just a small code base. In either case you must pray the PHP tyrants don't soon vote this into a runtime exception error, as when you retrofit your old code you're almost never going to find every instance of this.
Compare this situation with perl strict. Perl introduced "strict" mode with "use strict" a long time ago. That makes you my() every variable and its dog or you get a full blown error. But I'm pretty sure it doesn't affect array indices. In any event, if you don't agree with the perl devs, you just write "no strict" (or just disable this specific strict). No tyrrany. Freedom and choice. Perl, like PHP has never been strictly typed or declared. Perl will never force you to use strict. Never. So why is PHP?
PHP could have made it a configurable option. It would be really easy. But they didn't.
I have some projects with over 100k lines of PHP code. The simple fact that "fixing" this will make my code look extremely ugly, harder to read, less maintainable, and probably more prone to bugs is all the reason I need to decide that I will never "fix" my code. Not to mention it will be probably 20k lines of code that need to be "fixed", and it's a pointless pursuit because in the end I'll never find them all. (grep -P '[' ... ya right.)
So it will be log & ignore, or not log at all (though I still will need to see legit warnings somehow); or git clone php and change 2 lines of code and maintain my own version forever. In fact, it may be time to do a fork of PHP: sane-php or something.
Lastly, I'm willing to debate the philosophical points, especially using the RFC's wording as a basis; however, I'm not sure anyone is interested in taking the other side (please, hardcore PHP programmers only). I'll leave you with the arrogant wording from the RFC:
In most cases, accessing an undefined variable is a severe programming error. The current low classification is a legacy from the Dark Ages of PHP, where features like register_globals made conditionally defined variables more typical, and code quality standards were lower. [...] However, throwing an exception may complicate the upgrading of legacy code that currently suppresses the generation of notices wholesale, as the issue can no longer be ignored. Some people have even suggested that the use of undefined variables is a legitimate coding style choice.
"Legacy", "Dark Ages" indeed. Nice framing. "Legitimate coding style choice." How gracious.