La version qui ne posait aucun problème était la suivante :

<?php

error_reporting(E_STRICT);

class a { public function test($foo) {} }
class b extends a { public function test($foo, $bar) {} }

$b = new b();

?>

La version, qui était strictement identique fonctionnellement parlant, mais qui posait problème était quand à elle composée de trois fichiers.

Le premier fichier, nommons le a.php, contenait le code suivant :

<?php

class a { public function test($foo) {} }

?>

Le second fichier, nommons le b.php, contenait le code suivant :

<?php

class b extends a { public function test($foo, $bar) {} }

?>

Et le troisième et dernier fichier, all.php, contenait le code suivant :

<?php
error_reporting(E_STRICT);

require('a.php');
require('b.php');

$b = new b();
?>

A l'éxécution de all.php, PHP générait l'erreur suivante :

PHP Strict standards:  Declaration of b::test() should be compatible with that of a::test() in /path/to/b.php on line 3

En résumé, inclure deux classes à l'aide de require() ne revenait pas au même que de déclarer les deux classes dans le même fichier...

Afin d'être sur de mon fait, j'ai demandé à mes collégues et aux personnes présentes sur #jelix sur irc de confirmer qu'ils avait bien le même comportement, et à ma grande surprise, ce fût le cas.

Vous ne me croyez pas ? cela vous semble trop gros pour être vrai ? essayez...

Il y a 85% de chances, et voir même 100% de chances si vous n'avez jamais touché à la directive error_reporting de votre php.ini, que vous obteniez le même comportement.

En effet, error_reporting a pour valeur par défaut E_ALL.

Cela signifie que lorsque PHP interpréte le code de la première version, la directive error_reporting n'a pas la valeur E_STRICT, mais bien E_ALL, puisque l'appel à error_reporting(E_STRICT) n'a pas encore été éxécuté.

En effet, c'est lors de l'éxécution du script proprement dit, et donc après son interprétation, que l'appel à error_reporting(E_STRICT) est effectué et que error_reporting prend réellement la valeur E_STRICT.

Or, avec la seconde version qui fait appel à require(), les fichiers a.php et b.php sont inclus après l'interprétation du code et lors de son éxécution. Au moment des appels à require(), error_reporting a donc la valeur E_STRICT.

Voici donc la raison pour laquelle deux codes fonctionnellement identiques n'ont pas le même comportement : l'environnement d'éxécution n'est tout simplement pas configuré de la même manière dans les deux cas.

La solution du problème est donc très simple : Il suffit de donner la valeur E_ALL|E_STRICT à la directive error_reporting dans votre php.ini.

Vicieux, non ?