The story of one typo or strtr() replacing wrong characters

Recently there was a question on Russian Stack Overflow, from a guy claiming that strtr() works incorrectly. They even provided some proof-codes:

$value = 'B1000' ; // here we have zeros

$converter = array( '-' > '' ); // delete all dashes

$tr = strtr ( $value , $converter );

echo $tr ; // outputs 'B1111' - all 0s got replaced with 1s another example: $value = 'B1000' ; // we have zeros

$converter = array( '-' > '_' ); // replace all dashes to underscores

$tr = strtr ( $value , $converter );

echo $tr ; // outputs 'B1' - all zeros are gone

Although this problem was caused by a simple typo, I found it rather amusing, given the unexpected results, and I felt that it could be an interesting example showing how the type juggling works in PHP. Let's see:

All right, we just forgot the = character in the array definition, making it > "Greater than" operator instead of => array value assignment operator.

character in the array definition, making it "Greater than" operator instead of array value assignment operator. As a result we've got an '-' > '' expression ( '-' > '_' in the second example) that returns a boolean value

expression ( in the second example) that returns a boolean value It's all right for PHP to compare strings, based on the characters' codes: for the first example, an empty string is always less than a non-empty one, and therefore '-' > '' returns true in the second example, the code for dash character is 45 whereas underscore is 95, which makes '-' > '_' equal to 45 > 95 equal to false .

If we omit the key in the array definition, it is generated automatically, starting from 0. Therefore in the end the arrays would look like: in the first case array (0 => true) and in the second array (0 => false)

to use a value in the string manipulations, PHP will cast it to a string

when PHP casts a boolean to a string, true becomes 1 and false becomes just an empty string

So now you can tell that replacements went according to the following rules

['0' => '1'] in the first case

in the first case ['0' => ''] in the second

and naturally, we just got 0s replaced to 1s as well as 0s removed!