Pop quiz about PHP and something we’ve stumbled upon last week, while working on a client’s codebase.
Given the following code:
class Foo {
public $bar;
public function __construct($value) {
$this->bar = $value;
}
}
$a = new Foo('a');
$b = new Foo('b');
$c = new Foo('c');
$result = array_diff( [$a, $b, $c], [$a, $b] );
What would you expect the result to be?
1️⃣ Array( )
2️⃣ Array( [0] => Foo( [bar] => c ) )
3️⃣ Array( [2] => Foo( [bar] => c ) )
4️⃣ Object of class Foo could not be converted to string
I’ll give you some moments to think it over…
“Obviously” [not 🙄] the right answer is option 4 …
4️⃣
Object of class Foo could not be converted to string
… because for the array_diff
function …
Two elements are considered equal if and only if
(string) $elem1 === (string) $elem2
. That is, when the string representation is the same.
… and, adding insult to injury, objects don’t have a default string representation.
😱 🤦♂️ x 100
Funnily enough [not at all 😤] implementing the string conversion magic method …
public function __toString() {
return $this->bar;
}
… then option 3 becomes the answer …
3️⃣
Array( [2] => Foo( [bar] => c ) )
… because “arrays” in PHP don’t exist and, in reality, are nothig more than key-value maps in disguise, with the index numbers as the keys. 😕
This means you’d need to wrap it all around an array_values
call to “reset” all the indexes keys of the array map back to zero.
Guess I need to make this old article my new bed time reading, to read over and over and over again: PHP: a fractal of bad design / fuzzy notepad