PHP converts operands to whatever an operator needs: '10' + '5.5' is float(15.5) and 10 . 5 is "105". PHP 8.0 made bad input louder: '5 apples' + 1 still gives 6 but warns "A non-numeric value encountered", and 'apples' + 1 throws TypeError: Unsupported operand types: string + int instead of adding zero. === needs type and value to match; == converts first, by these rules:

<?php
$pairs = [[0, 'foo'], [42, ' 42'], [42, '42foo'], ['1e3', '1000'], [null, false]];
printf("%-16s %-6s %s\n", 'operands', '==', '===');
foreach ($pairs as [$a, $b]) {
printf("%-16s %-6s %s\n", json_encode($a) . ' vs ' . json_encode($b),
var_export($a == $b, true), var_export($a === $b, true));
}operands == === 0 vs "foo" false false 42 vs " 42" true false 42 vs "42foo" false false "1e3" vs "1000" true false null vs false true false
In the official php:7.4-cli Docker 514 image every row prints true under ==, because PHP 7 turned the string into a number: $token == 0 was true for any non-numeric token. Two numeric strings still compare as numbers, a trap for hashes. switch and in_array() compare loosely too (in_array('1e1', ['10']) is true), so pass true as in_array()'s third argument or use match (switch and match). "0", "", 0, [] and null are falsy; "0.0" and "false" are truthy.