# link to exceptions in autoload thread?

- Thread: https://externals.io/message/32532
- Original archive: https://news-web.php.net/php.internals/32532
- Started by Gregory Beaver on 2007-10-02T05:24:23+00:00
- Messages: 9
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #32532 — Gregory Beaver — 2007-10-02T05:24:23+00:00

URL: https://externals.io/message/32532#32532

Hi all,

Could someone point me to the message(s) explaining why the executor is
unstable when an exception is thrown in __autoload()?

Thanks,
Greg

---

## #32537 — Marcus Boerger — 2007-10-02T09:29:31+00:00

URL: https://externals.io/message/32532#32537 · In reply to: #32532

Hello Gregory,

  I don't recall any particular thread but Andi once explained why a few
things are instable when exceptions are pending. Some of that is no longer
the case so maybe it is time to reinvestigate the whole issue of pending
exceptions. But maybe that would result in an exception stack like in Java
and I am not sure whether I would not simply favor our current bahavior.

marcus

Tuesday, October 2, 2007, 7:24:23 AM, you wrote:

> Hi all,

> Could someone point me to the message(s) explaining why the executor is
> unstable when an exception is thrown in __autoload()?

> Thanks,
> Greg




Best regards,
 Marcus

---

## #32567 — Greg Beaver — 2007-10-02T19:25:22+00:00

URL: https://externals.io/message/32532#32567 · In reply to: #32537

Marcus Boerger wrote:
> Hello Gregory,
> 
>   I don't recall any particular thread but Andi once explained why a few
> things are instable when exceptions are pending. Some of that is no longer
> the case so maybe it is time to reinvestigate the whole issue of pending
> exceptions. But maybe that would result in an exception stack like in Java
> and I am not sure whether I would not simply favor our current bahavior.

Hi,

I actually don't mind the current behavior, although it would be nice if
instead of an `E_ERROR` it simply displayed the exception as if it were
uncaught (ignoring the exception handler - just shunt and display as an
Exception would).  Even this is not a big issue, I've been using die(new
Exception(...)) and it does the same thing.

What I was wondering is to understand __autoload()s internals a little
better.  Your message plus my investigation of the source leads me to
ask a pre-patch question:

I'd like to avoid my little fatal error trick if the user simply called
class_exists('Classname', true) and same for `interface_exists()`.  If I
provide a simple patch that would introduce a new HashTable of
classnames into EG() called EG(in_class_exists), and a new userspace
function in_class_exists() that returns true if __autoload() was called
by `class_exists()`, would that be an acceptable addition into PHP 5.3?

This way, my autoload handler could simply return if the user is
querying the existence of a class, and die pre-emptively with the
exception I want in other cases where an `E_ERROR` would result.

This feature would be extremely useful for PEAR2's implementation of
autoload.  Currently, I check the stack frame of the exception for
 `class_exists()` prior to `die()`ing with it, which is risky at best, and a
performance hog.

Thanks,
Greg

---

## #32592 — Marcus Boerger — 2007-10-03T14:52:09+00:00

URL: https://externals.io/message/32532#32592 · In reply to: #32567

Hello Greg,

Tuesday, October 2, 2007, 9:25:22 PM, you wrote:

> Marcus Boerger wrote:
> > […]

> Hi,

> I actually don't mind the current behavior, although it would be nice if
> instead of an `E_ERROR` it simply displayed the exception as if it were
> uncaught (ignoring the exception handler - just shunt and display as an
> Exception would).  Even this is not a big issue, I've been using die(new
> Exception(...)) and it does the same thing.

> What I was wondering is to understand __autoload()s internals a little
> better.  Your message plus my investigation of the source leads me to
> ask a pre-patch question:

> I'd like to avoid my little fatal error trick if the user simply called
> class_exists('Classname', true) and same for `interface_exists()`.  If I
> provide a simple patch that would introduce a new HashTable of
> classnames into EG() called EG(in_class_exists), and a new userspace
> function in_class_exists() that returns true if __autoload() was called
> by `class_exists()`, would that be an acceptable addition into PHP 5.3?

In theory `class_exists()` should simply return false if __autoload() cannot
find it. Why make that more complex? Is it avoiding the time to load and
compile the class? If so wouldn't normal code that checks for a class being
avaiable later use that class?

Check:
php -r 'function __autoload($c) { echo "Autoload: $c\n";} var_dump(class_exists("bla");'

You can even do class_exists($class_name, false) to avoid the call to to
__autoload().

> This way, my autoload handler could simply return if the user is
> querying the existence of a class, and die pre-emptively with the
> exception I want in other cases where an `E_ERROR` would result.

> This feature would be extremely useful for PEAR2's implementation of
> autoload.  Currently, I check the stack frame of the exception for
> `class_exists()` prior to `die()`ing with it, which is risky at best, and a
> performance hog.

> Thanks,
> Greg



Best regards,
 Marcus

---

## #32611 — Greg Beaver — 2007-10-03T20:07:41+00:00

URL: https://externals.io/message/32532#32611 · In reply to: #32592

Marcus Boerger wrote:
> > […]
> 
> In theory `class_exists()` should simply return false if __autoload() cannot
> find it. Why make that more complex? Is it avoiding the time to load and
> compile the class? If so wouldn't normal code that checks for a class being
> avaiable later use that class?

Here is the use case I am dealing with:

new PEAR2 user Joe User downloads PEAR2 package Blah, which depends on
package Foo, but does not download Foo/something happens and Foo is
erased accidentally/whatever.

Joe, not knowing anything about PEAR2 package Blah, is just trying it
out to see how it works, and so does the drill of:

<?php
include '/path/to/PEAR2/Autoload.php';
$a = new Blah;
$a->doSomething();
$a->doSomethingElse();
?>

This script results in:

Fatal Error: class PEAR2::Foo not found in
/path/to/PEAR2/Blah/SomeinternalClass.php on Line XX

Now what?  The error message doesn't tell Joe where to find PEAR2::Foo,
or any other useful information on how to find it, just that it can't be
found.  PEAR2, however, knows exactly where it should be found, and has
some idea of why it isn't there (package not installed).  In addition,
there is no stack trace that can be used to debug the call chain that
led to the problem if PEAR2::Foo *is* installed, and Joe reports the
problem to the maintainers of PEAR2::Blah.

Without my die(new Exception()), there is no way to pass this known
information back out of PEAR2_Autoload to Joe, and it makes both
development and debugging much more difficult, and unnecessarily so.

However, PEAR2 packages can also use `class_exists()` on drivers/optional
components to give a better error message.  For instance, if
hypothetical package PEAR2::Database is asked to instantiate the
Firebird driver, it could do:

if (!class_exists('PEAR2::Database::Firebird')) {
    throw new Exception('Could not locate Firebird database driver,
please install PEAR2::Database::Firebird package');
}

This error message is infinitely more useful than

Fatal Error: class PEAR2::Database::Firebird not found in ...

The fact is that there is no way to safely pass error information out of
an unsuccessful __autoload() if the script expects the class to simply
exist on the next line.  Perhaps you have a better idea, but the truth
is that I expect the default __autoload for PEAR2 to provide actual
useful debugging information.

I have already used this model to successfully debug conversion of an
existing PEAR package to the PEAR2 model as an exercise, and the stack
trace was REALLY helpful for locating what would have been a
particularly thorny problem - a class name with the incorrect CasING
that could not locate the file on disk.

The problem is that PEAR distributes code that is partially a black box
- the user is not expected to understand all of the intricate workings,
but just to use it to speed up their own development.

I use `die()` inside PEAR2's autoload because it would be a fatal error
anyways - if PEAR2's autoload didn't work, the class will not be found
by the definition of how PEAR2's directory structure and class naming
conventions work.

Perhaps you have a better idea of how to pass out a customized error
message and stack trace, but as it stands now, __autoload() is extremely
debugging-unfriendly.  Adding the ability to determine whether
 `class_exists()` is the source of the autoload would increase its
debugging-friendliness exponentially for my purposes, and would not
require major changes to the engine.

> Check:
> php -r 'function __autoload($c) { echo "Autoload: $c\n";} var_dump(class_exists("bla");'
> 
> You can even do class_exists($class_name, false) to avoid the call to to
> __autoload().

This, as you say, would mean that autoload would not be called.  Thus
this code:

if (!class_exists('PEAR2::Database::Firebird', false)) {
    throw new Exception('Could not locate Firebird database driver,
please install PEAR2::Database::Firebird package');
}
$driver = new PEAR2::Database::Firebird(...);

would always throw the exception, which defeats the purpose of using
class_exists to get a friendlier error message in the first place.

Greg

---

## #32612 — johannes@php.net — 2007-10-03T20:23:22+00:00

URL: https://externals.io/message/32532#32612 · In reply to: #32611

Greg,


> Now what?  The error message doesn't tell Joe where to find PEAR2::Foo,
> or any other useful information on how to find it, just that it can't be
> found.  PEAR2, however, knows exactly where it should be found, and has
> some idea of why it isn't there (package not installed).  In addition,
> there is no stack trace that can be used to debug the call chain that
> led to the problem if PEAR2::Foo *is* installed, and Joe reports the
> problem to the maintainers of PEAR2::Blah.
> 
> Without my die(new Exception()), there is no way to pass this known
> information back out of PEAR2_Autoload to Joe, and it makes both
> development and debugging much more difficult, and unnecessarily so.

function __autoload($a) {
   $b = `debug_backtrace()`;
   if ($bt[1]["function"] == "class_exists") {
       echo "in get_class";
   }
}

should work quite well without obscure engine hacks - or am I missing
something?

johannes

---

## #32613 — johannes@php.net — 2007-10-03T20:27:36+00:00

URL: https://externals.io/message/32532#32613 · In reply to: #32612

> Greg,
> 
> 
> > […]
> 
> function __autoload($a) {
>    $b = `debug_backtrace()`;

This, of course, should have been
   $bt = `debug_backtrace()`;
;-)

>    if ($bt[1]["function"] == "class_exists") {
>        echo "in get_class";
>    }
> }
> 
> should work quite well without obscure engine hacks - or am I missing
> something?
> 
> johannes

---

## #32616 — johannes@php.net — 2007-10-03T20:54:45+00:00

URL: https://externals.io/message/32532#32616

> I do that now, but it is a severe performance hog as well as being
> fugly.  Also, if you use spl_autoload_register, the frame is $bt[2].  In
> other words, it's possible, but still an ugly, unnecessary hack with
> lots of potential pitfalls caused by the inability to customize an error
> message when a class doesn't exist.

Well, the real performance issue there is searching through the file
system - and I doubt performance is important for an error handler. If
you need performance write proper code without errors which need
handling.

johannes

---

## #32684 — Gregory Beaver — 2007-10-06T20:23:58+00:00

URL: https://externals.io/message/32532#32684

Marcus Boerger wrote:
> Hello Greg,
> 
>   I think Johannes has a point here. It is doable in PHP already and you
> don't hit a performance issue here as you are showing the message only
> when the class is not present. That is just add Johanne' code after you
> know that your autoload was responsible but cannot find the class.

Hi,

Just to help with the volume of mail - I know when an idea will not be
implemented, and I've got the hacky code in my implementation (and it
works even if the smell of the code repulses me :), so this thread can
die now for the more important issues.

Thanks,
Greg
