Re: strange autoload behavior
| From: | Marcus Boerger | Date: | Thu, 17 Jul 2008 20:46:24 +0000 |
| Subject: | Re: strange autoload behavior | ||
| References: | 1 2 3 4 5 6 7 8 9 10 11 | Groups: | php.doc php.internals |
| Request: | Send a blank email to phpdoc+get-969379124@lists.php.net to get a copy of this message | ||
Hello Jochem,
Thursday, July 17, 2008, 7:38:01 PM, you wrote:
> Marcus Boerger schreef:
>> Hello Jochem,
>>
> ...
>>> I just posted another mail to internals in which I attempt to detail the
>>> __autoload behaviour 'issues' ... it includes something that wants to be a
>>> test suite when it grows up ... it might help someone to investage/determine
>>> what __autoload() does/should do:
>>
>>> http://iamjochem.com/autoload_behaviour_tests.zip
>>
>> Great! More tests :-)
>>
>> It is quite a lot of stuff and I'd like to see this turned into .phpt's.
> it looks more than it is, the runtests.sh script makes viewing the results
> of the variations in settings/code easier.
> if you unzip the file and execute ./runtests.sh with no args it goves you
> all the options ... at this stage I wrote primarily to figure out what
> actually happens under any number of conditions.
> I'd love to take a shot at converting them to .phpt I see 3 problems
> 1. I don't know .phpt (I can solve this)
http://qa.php.net/write-test.php
http://somabo.de/talks/200703_montreal_need_for_testing.pdf
or .pps
> 2. I have no idea what to expect and therefore test for
> (this needs to be determined/clarified!)
Write the tests as good as you can and if you are unsure about the result
mail.
> 3. In the case that I need to test for an uncaught Exception I wonder
> how to determine a pass (ie uncaugh exception thrown as expected) given
> that the exact output is dependent on the full path of the relevant script
Zend/tests/exception_008.phpt is a test for an uncaught exception that is
made dynamic enough to work everywhere. In general we use EXPECTF as soon
as error messages or exceptions are expected. Then we replace:
- path's including the last path separator with '%s'
- line numbers with '%d'
- object identifiers '#<num>' with '#%d'
marcus
> any advice as to how to proceed, especially with regard to point 2.
> rgds,
> Jochem
>>
>> marcus
>>
>>>> That is they
>>>> are simply ignored.
>>
>>> and so I thought :-) which is why some of my test's output "wtf!" :-)
>>
>>> as always, thanks for your feedback,
>>> regards,
>>> Jochem
>>
>>>> And once all __autoload work is done and the class
>>>> still doesn't exist an E_ERROR is issued. The work around for cases where
>>>> the class must not exist (e.g. when no E_ERROR is needed would be
>>>> collecting the exceptions. That is the base Exception class would get an
>>>> additional property and getter:
>>>> private $previous_exception;
>>>> function public getPreviousException();
>>>> That way we could let the exceptions bubble up (though some smaller engine
>>>> changes are necessary).
>>
>>> currently you can throw an exception out of __autoload() unless __autload()
>>> is triggered by the 'new' syntax or by a static method call (e.g.
>>> MyClass::myMethod()),
>>> with other 'triggers' (e.g. call_user_func()) the exception comes through ...
>>> in cases that it doesn't you can get an exception out of __autoload() via the
>>> eval() trick [see below] ... I don't suppose there is anyway of asking the engine
>>> which way __autoload() was triggered from inside the __autoload() code?
>>
>>>> marcus
>>>>
>>>> Thursday, July 10, 2008, 7:14:33 PM, you wrote:
>>>>
>>>>> Derick Rethans schreef:
>>>>>> On Thu, 10 Jul 2008, Gergely Hodicska wrote:
>>>>>>
>>>>>>>> exceptions thrown during autoload are ignored.
>>>>>>> And one more thing, this is in the manual:
>>>>>>> "Note: Exceptions thrown in __autoload function cannot be caught
>>>>>>> in the catch
>>>>>>> block and results in a fatal error."
>>>>>>>
>>>>>>> I think your explanation makes much more clear what happens, maybe it
>>>>>>> would
>>>>>>> worth to upgrade the manual. While the quoted text suggests that that
>>>>>>> if throw
>>>>>>> an exception I just can't catch it and will bubble up to top level
>>>>>>> and this
>>>>>>> cause the fatal error.
>>>>>> You can actually catch it *in* the autoload method, it just wouldn't
>>>>>> bubble out of it.
>>>>> the manual could do with that tidbit, maybe also the hack for 'getting the
>>>>> exception out' of __autoload() ...
>>>>> function __autoload($class)
>>>>> {
>>>>> try {
>>>>> throw new Exception('foo');
>>>>> } catch (Exception $e) {
>>>>> self::handleDebug($e);
>>>>>
>>>>> if (!class_exists($class, false))
>>>>> eval(sprintf('
>>>>> class %1$s
>>>>> {
>>>>> public function __construct() {
>>>>> throw new AL_Exception("Class %1$s not found: %2$s"); }
>>>>> public function __call($m, $a) {
>>>>> throw new AL_Exception("Class %1$s not found: %2$s"); }
>>>>> public static function __callStatic($m, $a) {
>>>>> throw new AL_Exception("Class %1$s not found: %2$s"); }
>>>>> }', $class, $e->__toString()));
>>>>>
>>>>> }
>>>>> }
>>>>> which works best when __autoload() isn't triggered by
>>>>> class_exists("Foo", true)
>>>>
>>>>>> regards,
>>>>>> Derick
>>>>>>
>>>>
>>>>
>>>>
>>>>
>>>> Best regards,
>>>> Marcus
>>>>
>>>>
>>
>>
>>
>>
>> Best regards,
>> Marcus
>>
>>
Best regards,
Marcus