Bug #65317 [Opn]: spl autoload won't work inside an autoload
| From: | laruence@php.net | Date: | Tue, 23 Jul 2013 17:09:26 +0000 |
| Subject: | Bug #65317 [Opn]: spl autoload won't work inside an autoload | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-180438@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=65317&edit=1
ID: 65317
Updated by: laruence@php.net
Reported by: tyrael@php.net
Summary: spl autoload won't work inside an autoload
Status: Open
Type: Bug
Package: SPL related
Operating System: linux
PHP Version: 5.4.17
Block user comment: N
Private report: N
New Comment:
my previous comment is not right.
it real reason is here, in (zend_lookup_class_ex):
/* The compiler is not-reentrant. Make sure we __autoload() only during run-
time
* (doesn't impact fuctionality of __autoload()
*/
if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
if (!key) {
free_alloca(lc_free, use_heap);
}
return FAILURE;
}
so, the error is trigged in compiling MyAbstract...
so is in compile time...
so,,
Previous Comments:
------------------------------------------------------------------------
[2013-07-23 17:05:35] tyrael@php.net
it was introduced by Dmitry:
http://git.php.net/?p=php-
src.git;a=commitdiff;h=9305339d94c701e8eda93dbf0231d70918ef4a6a
"Changed "instanceof" and "catch" operators, is_a() and is_subclass_of()
functions to not call __autoload()."
so nothing about generic recursion protection or explicitly talking about calls
from another autloader method.
I would guess this specific scenario wasn't really intentional, but let's ask
Dmitry about his thoughts.
Personally I think that it is rather surprising and unintuitive and it was a
little bit tricky to figure it out why the code didn't worked as I've expected.
------------------------------------------------------------------------
[2013-07-23 16:51:46] laruence@php.net
Hey, it should be a intention behavior:
zend_class_entry *zend_fetch_class_by_name(const char *class_name, uint
class_name_len, const zend_literal *key, int fetch_type TSRMLS_DC) /* {{{ */
{
zend_class_entry **pce;
int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
it seems try to prevent some recursive autoload, then stack overflow
so.... won't fix IMO (it's really a edge case :))
maybe document it instead?
thanks
------------------------------------------------------------------------
[2013-07-23 16:26:52] tyrael@php.net
Description:
------------
I just bumped into an issue, where we had a Strict error triggered about an
abstract class, which caused our autoloader to fail.
It seems that the autoloader won't be called when you try to reference a not-yet-
loaded class from an error handler triggered by an autoloader function.
I think that the attached test script makes the scenario more clear(sorry for the
eval part, I didn't wanted to upload multiple scripts), but feel free to ask me if
you need more info.
ps: it seems that this never worked http://3v4l.org/AQCue but I
couldn't find any
previous reports or notes/docs on the topic.
Test script:
---------------
<?php
spl_autoload_register(function($class){
if ($class == 'MyConcrete') {
eval('
class MyConcrete extends MyAbstract {
public static function createInstance() {}
}
');
} elseif ($class == 'MyAbstract') {
eval('
abstract class MyAbstract {
public abstract static function createInstance();
}
');
} else {
eval('class '.$class.'{}');
}
});
set_error_handler(function($errno, $errstr, $errfile, $errline){
$myclass = new MyClass;
});
$concrete = new MyConcrete;
$myclass = new MyClass;
Expected result:
----------------
trigger the autoloader from the error handler and load the class
Actual result:
--------------
Fatal error: Class 'MyClass' not found in index.php(14) : eval()'d code on line 3
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=65317&edit=1