tomw,
@tomw@mastodon.social avatar

Pop quiz: can you spot the problem in this PHP snippet? I just got tripped up by it and it was very Not Fun. (This is rewritten to be a minimal example.)

if ( $coolness > 10 ) {
define('COOL_MODE', true);
}

if ( COOL_MODE == true) {
echo 'You are cool.';
}

18+ abucci,
@abucci@buc.ci avatar

I just ran this in php 7.4 and php 8.2, and there is different behavior.

In 7.4, if $coolness is not set to anything before this code snippet is run, there are warnings but "You are cool" is printed. If $coolness is set, the same warning about COOL_MODE is thrown as is thrown when $coolness is not set, but again "You are cool" is printed no matter what $coolness is set to. Very weird.

The same happens, without warning, if you use 'COOL_MODE' in that check (with quotes, which is what the warning leads you to try). The problem seems to be that when you define COOL_MODE to true it's set to 1 (!). So you really want to check COOL_MODE against 1, not true, in that second if. However, you don't want to use 'COOL_MODE' with quotes--that doesn't work!

This is such a bizarre combination of errors and behaviors 🤯

8.2 behaves a little more gracefully. If $coolness is not set, there's a warning about that. Then there's also an error that COOL_MODE is undefined. Both seem useful. If $coolness is set, but not > 10, then an error is thrown that COOL_MODE is undefined, which also seems useful. The snippet works as expected if $coolness is set and is greater than 10, even with the check against true in the second if.

18+ tomw,
@tomw@mastodon.social avatar

@abucci Yes, that's pretty much it!

The PHP7 behaviour is that if the constant COOL_MODE is undefined, then it returns the string "COOL_MODE". This in turn evaluates to true or 1, triggering code paths you didn't expect.

PHP8 has the more 'correct' but also breaking behaviour that I ran into: if you try to make any comparison with an undefined constant, then instead of returning false it returns an error. And if you do not catch it then it is a fatal error, your page returns a 500.

18+ abucci,
@abucci@buc.ci avatar

@tomw Wow. I'm not a PHP programmer and only sorted out what I said by hacking in REPLs, but this all sounds frustrating. Accessing dynamically defined variables like this seems fraught with peril no matter what the default behavior is.

tomw,
@tomw@mastodon.social avatar

@abucci Yeah, they're trying to fix a historical mistake but making a bit of a mess in the process...

datarama,
@datarama@hachyderm.io avatar

@tomw @abucci In Queinnec's "Lisp in Small Pieces" from 1994, this exact behaviour (except, obviously, with symbols instead of strings) is described as undesirable behaviour the Lisp community learned the hard way to get rid of ... at some point in the early 70s.

(and also how misguided it was to "reduce errors" ... by allowing people to do things they almost certainly didn't want to. Though it made for some neat tricks in early algebra systems.)

tomw,
@tomw@mastodon.social avatar

@datarama @abucci In general – and hardly anyone agrees with this – I preferred old-PHP's "render something, even possibly completely the wrong thing if you have a weird logic bug" approach to new-PHP dropping fatal errors and hard stops all over the place

Geoff,
@Geoff@mastodon.cloud avatar

@tomw @datarama @abucci yes. Php was successful because it was a horrible mess that worked if idiots used it. They are now trying to make it a proper language, but all the code that the idiots wrote is still running on live servers everywhere.

It's our own fault: we should have pushed back when they forcibly removed register_globals. Once they got away with that absolute catastrophuck, we were doomed.

tomw,
@tomw@mastodon.social avatar

@Geoff @datarama @abucci I think it's more that they want to focus on an audience that's building "apps" instead of pages.

When you're just adding some widget to a page, you want it to just error out and the rest of the page to still continue. You don't want execution to 'correctly' stop on error.

seedyh,
@seedyh@qoto.org avatar

@tomw if $coolness <= 10, COOL_MODE never gets initialized?

18+ tomw,
@tomw@mastodon.social avatar

@seedyh Yes - and then what happens?

catbuttes,
@catbuttes@freeradical.zone avatar

@tomw I'm not a PHP person, but does it always define the COOL_MODE constant at startup, ignoring the conditional nature of the define?

18+ tomw,
@tomw@mastodon.social avatar

@catbuttes Not quite! In a way it's the opposite of that.

18+ janeadams,
@janeadams@vis.social avatar

@tomw I don't actually know PHP, but is it that COOL_MODE is a string, not a var name? Like it should be define(COOL_MODE, ...?

18+ tomw,
@tomw@mastodon.social avatar

@janeadams Regrettably, PHP does take a string to define() to set the name of the constant. In fact, passing the bare constant name is a common error:

php > define(COOL_MODE, true);

Warning: Uncaught Error: Undefined constant "COOL_MODE" in php shell code:1

18+ janeadams,
@janeadams@vis.social avatar

@tomw ohh haha that is cursed 🧟‍♀️

tomw,
@tomw@mastodon.social avatar

Clue: this worked in PHP7, if by worked you mean "failed in a somewhat worse way". It does not work in PHP8.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • PowerRangers
  • DreamBathrooms
  • thenastyranch
  • magazineikmin
  • hgfsjryuu7
  • Youngstown
  • InstantRegret
  • slotface
  • khanakhh
  • rosin
  • ngwrru68w68
  • kavyap
  • tsrsr
  • tacticalgear
  • Leos
  • cisconetworking
  • everett
  • vwfavf
  • GTA5RPClips
  • osvaldo12
  • Durango
  • mdbf
  • modclub
  • tester
  • cubers
  • ethstaker
  • normalnudes
  • anitta
  • All magazines