问题
While attempting to implement some kind of error handling when my __autoload() function fails to load a file I stumbled upon this little 'oddity'.
According to http://nl.php.net/autoload Exceptions thrown from within the __autoload() function can be caught in a catch block since PHP version 5.3+.
Note: Prior to 5.3.0, exceptions thrown in the __autoload function could not be caught in the catch block and would result in a fatal error. From 5.3.0+ exceptions thrown in the __autoload function can be caught in the catch block, with 1 provision. If throwing a custom exception, then the custom exception class must be available. The __autoload function may be used recursively to autoload the custom exception class.
This works perfectly for the type of error handling I had in mind. The example below works just like I want it to (It throws an exception and it's caught):
function __autoload($class) {
throw new Exception();
}
try {
new UndefinedClass();
}
catch (Exception $e) {
echo 'damnit, it no work!';
}
Output: damnit, it no work!
If however I try the same concept with a static method call from a undefined class, Exceptions are not thrown, instead I get fed a fatal error.
try {
$a = UndefinedClass::someRandomStaticMethod();
}
catch (Exception $e) {
echo 'meh, it no work!';
}
Output: Fatal error: Class 'UndefinedClass' not found in ***** on line 16
The code above does not work. No Exception is thrown. ( same __autoload() function is used ).
http://nl.php.net/autoload mentions nothing about this usecase and this leaves me wondering if I'm doing something terribly wrong here? How can I make my __autoload() function throw exceptions on static method calls of a non-existent class?
If this is simply not possible with the __autoload() function, does spl_autoload() allow this kind of Exception throwing?
@Galled
Based on the link you provided I changed the __autoload() function to this:
function __autoload($class) {
eval('
class ' . $class . ' {
};
');
throw new Exception('Im an Exception!');
}
Using this version the fatal error in question is no longer fed to my monitor. However, it will now feed me with a different fatal error: the fact that the someRandomStaticMethod() doesn't exist.
I could of course include the declaration of the method within the eval() call. But this is not workable solution, as I would have to redeclare every class my project contains within the __autoload() function just to be able to avoid said fatal error. It's also interesting to know that no Exception is caught, as it seems the fatal error occurs before the Exception is handled, if it is even thrown in the first place.
回答1:
I somewhat managed to solve the problem by expanding on the suggestions from Galled. After some more reading, especially here: http://nl.php.net/manual/en/function.spl-autoload-register.php#84086 I wrote the following.
function __autoload($class) {
...
/* if something and/or everything fails */
eval('
class ' . $class . ' {
public function __construct() {
throw new Exception(\'Im an Exception!\');
}
public static function __callstatic($method, $arguments) {
throw new Exception(\'Im an Exception!\');
}
};
');
}
This variation will now throw Exceptions
on both use-cases. regardless on the existence of methods within a class.
While the above works, I'm hoping someone can provide a solution that doesn't touch the eval()
function. As, for some reason, I feel like I just molested PHP.
来源:https://stackoverflow.com/questions/8213488/autoload-fails-to-throw-an-exception-when-it-fails-to-load-a-class-on-a-static