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