« | Weak typing and PHP8 |
» |
I'm currently moving our codebase from PHP7 to PHP8. In PHP8 the developers are strongly encouraging users to explicitly declare variables and to move away from implicit casting but here's a doozy where they've arbitrarily changed the way implicit casting is done.
Consider this code:
<?php echo "\nOn PHP ".phpversion()." ...\n\n"; $number = 1; $string = 'a'; if ( $string > $number ) echo "'".$string."' is greater than ".$number; else echo "'".$string."' is less than or equal to ".$number; echo "\n\n";
So what does it do? Well first it outputs the PHP version and then it defines two variables, a number called $number
with a value of 1
and a string called $string
with a value of 'a'
.
It then compares them using the greater than operator and outputs text to tell us if the test evaluated to true or false.
Programmers of strongly typed languages will be slightly bemused by all of this but with PHP it's valid code and you can expect that PHP will cast variables in a fairly natural language sort of way. That's fine on the whole ... except that there are edge conditions and this is one.
Let's run this code first using PHP 5 just to establish some history. Here's the output:
On PHP 5.6.40-47+ubuntu16.04.1+deb.sury.org+1 ... 'a' is less than or equal to 1
This is as I'd expect being a PHP hack. In this situation PHP says "hmmm ... looks like you're doing a numeric compare so I'll cast the string $string
to a numeric first and then do the compare". The string 'a' has no numbers in it so it casts to zero and zero is less than or equal to one and, as you can see, that's what the script outputs.
OK, let's run the same script on PHP7.
On PHP 7.4.33 ... 'a' is less than or equal to 1
Super, so we know where we are now. It'll be easy to port this code to PHP8 and we'll get the same result. So here it is running on PHP8:
On PHP 8.1.2-1ubuntu2.14 ... 'a' is greater than 1
Wow!
So I think what's happened here is that they've decided to treat the comparison as a string compare and hence cast the second variable, not the first. So $number
is cast to '1'
and, in a string compare 'a'
is greater than '1'
.
Oh, and I did try reversing the variable order in case it was casting based on the type of the first variable. It's not. In PHP5 and PHP7 it always casts both to numeric, in PHP8 it casts both to strings.
At this points advocates of strongly typed languages will point out that this is precisely the sort of thing that makes weakly typed languages dangerous, and they're right. Be that as it may I'm now in a situation where the language behaviour has changed and that's screwing up my code so I'm going to have to do a code review.
Tags: websites | Written 16/10/23 |
« | » |