bartzy
bartzy

Reputation: 328

Calling to static methods for unknown classes doesn't trigger an exception catch in __autoload

For some reason, exceptions thrown in an __autoload function aren't being caught when trying to call a static method on a class that doesn't exist yet (PHP 5.3.9).

See this sample code:

<?php
function __autoload($class)
{
    throw new Exception('loaded ' . $class . "\n");
}


try {
    echo "Object: ";
    $test = new Log();
}
catch (Exception $e)
{
    error_log($e->getMessage());
}

// Exception is caught with static var.
try {
    echo "Static var: ";
    Log::$blah;
}
catch (Exception $e)
{
    error_log($e->getMessage());
}

// Fatal error occures with static method.
try {
    echo "Static method: ";
    Log::blah();
}
catch (Exception $e)
{
    error_log($e->getMessage());
}

The exception is caught on the first 2 cases (new object and a static property of an unknown class), but is not caught on calling the static method.

Upvotes: 1

Views: 2582

Answers (2)

hakre
hakre

Reputation: 198199

PHP mixes errors and exceptions. In this case, the fatal error is "thrown" before the exception could be caught. It's about priorities. Calling an undefined function and giving the fatal error has a higher priority here than handling the exception, the code already stopped (Demo). Fatal errors itself can not be catched.

As you can not catch fatal errors with a try/catch block, your script stops at the fatal error.

Same would be for an undefined static property of a defined class. It would trigger a fatal error as well you won't be able to catch.

You can however turn errors into exceptions and catch those, however this does not work with fatal errors (Demo). I assume this is the root limitation you're running into: Fatal error brings script execution down, regardless if it appears inside a try/catch block or not. Exception handling is brought down as well.

Additionally, PHP 5.5.0-dev and PHP 5.4.0beta2-dev crashes with a simliar to yours code example. Which makes me believe that in the upcoming PHP version there will be a bug which could be considered a flaw. It might be worth to report this against PHP 5.4.

See also Exception slipping exception handler which illustrates your problem without the overhead of __autoload.

Upvotes: 2

Nayjest
Nayjest

Reputation: 1089

Yes, PHP have a problems with exceptions thrown in an __autoload. But you can use one interesting trick:

function __autoload($class)
{
    eval("class $class {            
        static function __callStatic(\$name,\$val){
            throw new Exception('Loaded ' . $class . PHP_EOL); 
        }         
    }");    
    throw new Exception('Loaded ' . $class . PHP_EOL);
}

And don't forgot to implement work with namespaces in evaled expression.

Upvotes: 1

Related Questions