PHP 5 : le mystère de la fonction __autoload()

20/05/2006 17:44:50

Je pense avoir découvert une différence fondamentale de comportement dans la fonction magique __autoload() entre PHP 5.0.x et PHP 5.1.x.

En effet, le manuel PHP indique à ce sujet :

Note : Les exceptions lancées depuis la fonction __autoload() ne peuvent être interceptées par un bloc catch : elles provoqueront une erreur fatale.

Or, cela est bel et bien vrai en PHP 5.0.x (jusqu’à PHP 5.0.5), mais est devenu faux en PHP 5.1.x (à partir de PHP 5.1.0), où les exceptions sont traitées correctement.

Pour vous en convaincre, saisissez les commandes suivantes en tant qu’utilisateur normal sur un shell Bash :

wget http://storage.e-t172.net/php-autoload/php-autoload && chmod +x php-autoload && ./php-autoload

Ce script va télécharger PHP 5.0.5 et PHP 5.1.0, les compiler (sans les installer, rassurez-vous) et éxécuter ce script PHP successivement avec les deux versions fraîchement compilées :

 <?php
define(‘CLASS_DOES_NOT_EXIST’TRUE);

function __autoload($class)
{
    if (CLASS_DOES_NOT_EXIST)
    {
        // On cree une  »fausse classe » pour ne pas generer d’erreur  »class not found »
        eval(‘class ’.$class.‘ { }’);
        
        throw new Exception(‘The class ’.$class.‘ does not exist’);
    }
}

try
{
    // Tentative d’instanciation d’une classe qui va appeller __autoload()
    $test = new test();
    
    // Commentez la ligne d’instanciation pour tester les appels statiques
    test::go();
}
catch (Exception $e)
{
    var_dump($e);
}
?>
 

Voici les résultats tels que le script Bash les affiche :

-----------
PHP 5.0.5 :
-----------

Fatal error: Function __autoload(test) threw an exception of type 'Exception' in /root/php-autoload-test/php-autoload.php on line 28
-----------
PHP 5.1.0 :
-----------
object(Exception)#1 (6) {
  ["message:protected"]=>
  string(29) "The class test does not exist"
  ["string:private"]=>
  string(0) ""
  ["code:protected"]=>
  int(0)
  ["file:protected"]=>
  string(40) "/root/php-autoload-test/php-autoload.php"
  ["line:protected"]=>
  int(11)
  ["trace:private"]=>
  array(1) {
    [0]=>
    array(4) {
      ["file"]=>
      string(40) "/root/php-autoload-test/php-autoload.php"
      ["line"]=>
      int(18)
      ["function"]=>
      string(10) "__autoload"
      ["args"]=>
      array(1) {
        [0]=>
        string(4) "test"
      }
    }
  }
}

Conclusion : à partir de PHP 5.1, OUI vous pouvez thrower des exceptions depuis une fonction __autoload(), et je sens que ça va en ravir plus d’un.

En fait, il semblerait que ce problème de documentation soit connu, mais il est enfoui dans les commentaires du rapport de bug concerné (#31102) :

helly has introduced a way to catch the exceptions, so it needs to be documented.

En effet, il serait temps !

Rédigé par e-t172 |

Les commentaires sont fermés.

URL de trackback |