array_slice confused about negative length

Why is the second array below empty? It seems array_splice cannot grok negative length, despite its docs.

<?php
$array
= array('a' => '1');

// GOOD
print_r(array_slice($array, 010));

// WTF. Why empty array?
print_r(array_slice($array, 0,  -10));
?>

Array
(
    [a] => 1
)
Array
(
)

Identical arrays vs equal arrays

There is a small problem when comparing arrays -- you can find arrays where array_diff comes back empty and yet, the arrays are not identical.

<?php
$array1
= array(
 
'foo' => 'foo',
 
'bar' => 'bar',
);

$array2 = array(
 
'bar' => 'bar',
 
'foo' => 'foo',
);

var_dump(array_diff($array1, $array2)); // Result: empty array.
var_dump($array1 == $array2); // Result: true.
var_dump($array1 === $array2); // Result: false.
?>

»

Numeric and integer keys

<?php
$a
= 1;
$b ->$a = 'foo';
var_export((array)$b);
var_export(array(1 => 'foo'));
?>

Results:
array (
  '1' => 'foo',
)array (
  1 => 'foo',
)

Observe the '1'. The array element after casting can not be reached via the [] operator. (And no, "'1'" wont do the trick.)

Even more hexadecimal fun

Some functions working on floats accept hexadecimal numbers while others don't:

<?php
print sin('15');
print
sin('0xF');
var_dump(round('15'));
var_dump(round('0xF'));
?>

You will see a float(0) for the second one if your PHP version is lower than 5.3.0. In PHP 5.3.0 and ongoing, both of these functions support hexadecimal numbers, however the explicit casting still does not.

Props go to Stan Vassilev for this one and also in general for being a great source of WTFs :)

Explicit and implict casting

PHP automatically casts strings to integers when doing arithmetic. However, intval($string) and $string + 0 is not the same! The first one works on numbers only, as described under String conversion to numbers in the manual, however, the latter is happy to accept numeric strings which again means that hexadecimal numbers are accepted. Compare print "0xf"+0 to intval("0xf").

Variable names

A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores.

Compare to:

<?php
$a
= 1;
$
$a = 'foo';
print ${
1};
?>

So the restriction that the variable name can not start with a number is only enforced by the parser and even then it's fairly easy to circumvent. Maybe it would have been simpler to explain and implement if the definition would be "A valid variable name contains any number of letters, numbers, or underscores".

String comparison

This WTF is documented but a WTF none the less:

If you compare two numerical strings, they are compared as integers.

. You need to add the definition of numerical strings to get the WTF:

Numeric strings consist of optional sign, any number of digits, optional decimal part and optional exponential part. Thus +0123.45e6 is a valid numeric value. Hexadecimal notation (0xFF) is allowed too but only without sign, decimal and exponential part.

. So for example "15" == "0xF".

version_compare

<?php
echo version_compare('anaconda', 'acromantula');
echo
version_compare('baby', 'blister');
echo
version_compare('change', 'cloister');
echo
version_compare('deviant', 'defines');
echo
version_compare('anaconda', 'blister');
echo
version_compare('baby', 'defines');
echo
version_compare('cloister', 'defines');
echo
version_compare('places', 'races');
?>

If you can tell what the output of this is going to be and why then congratulations.

»

Looping

Quoting literally: Note that in PHP the switch statement is considered a looping structure for the purposes of continue.

The beauty of string parsing, parting shot

Did you know that {$array} is tokenized as

<?php
 
array (
   
0 => 'T_CURLY_OPEN',
   
1 => '{',
  ),
  array (
   
0 => 'T_VARIABLE',
   
1 => '$array',
  ),
 
'}',
?>

however ${array} gets parsed into

<?php
 
array (
   
0 => 'T_DOLLAR_OPEN_CURLY_BRACES',
   
1 => '${',
  ),
  array (
   
0 => 'T_STRING_VARNAME',
   
1 => 'array',
  ),
 
'}',
?>

»
Syndicate content