FAQ
Hi,

I've been using namespaces for a few months now, and I feel a need for a
specific solution.

I've been thinking a lot about this, and I will explain everything here.

Basically the goal is to be able to overload namespace resolution (ie.
overloading new and static calls).

Basically (case 1), the user would create a function
__resolveclass($classname, $cur_namespace, $used_namespaces) which would
return a string. When new or a static call happens, this function is
called and the final call happens to whatever was returned.
The second argument would contain the current namespace (where the call
happened) and the last one would contain list of "used" namespaces.

It is possible to implement a cache (eg. if the same class is called we
just get the last value we got from __resolveclass()) but in this case a
function like clear_cache_resolver_cache() would be needed.

Another implementation (case 2) of this would be to create virtual
namespaces. In this case a function create_virtual_namespace($namespace,
$callback) would be created, and any new/static call on a class within
the given namespace would call $callback.

The basic idea behind this is to allow this kind of calls :

(from global scope)

use something;
$database = new virtual::SQL();
virtual::SQL::DoSomethingInteresting();

Both calls would call either :

Case 1: __resolveclass('virtual::SQL', '', array('', 'something'));
Case 2: my_callback('virtual', 'SQL'); (first parameter would be the
virtual namespace, the second one would be the class name).

While working with namespaces, I basically had namespaces extending
other namespaces (a collection of classes which extends another
collection of class, and all implement the same interface). However in
some cases one of the class has no need to be extended. In this case
it's just not created.
In order to implement this, I wrote my own "class resolver function"
which will lookup the class' file in current namespace, and in each
"parent namespace" until it finds it, then returns the class name so I
can do a new $class().

Another case where this is necessary is on a totally unrelated project:
we are working on a quite big framework, and the same codebase is being
used for more than 100 websites. The codebase itself is really huge, and
we replace parts as time passes by, and try to write new "modular" code.

Our need was to overload creation of some classes, but only for some
sites which have really specific needs. Since some of those classes are
static, a class factory isn't good enough, and (even if it's our goal)
we can't rewrite the whole code to make it new and better.



Being able to overload the new operator would allow us to make a better
class lookup to fit our needs, and probably other people's needs too,
which can't just be implemented in PHP (the class lookup).

I'm perfectly aware of the risks of obscure code spawning from the hands
of various people if this gets implemented, it was the same when classes
were implemented, when __autoload() was used (I saw people do what I
wrote here using __autoload and eval() to create an empty class
extending the target class on the fly) and there will be with
namespaces, probably with unicode support too.
You can't just create something and expect everyone will use it right,
but at least it's possible to document it and help people avoiding
non-maintainable code.

Anyway right now this is more on the discussion step, I think as PHP
5.3.0 gets released with namespaces, the need for this kind of solution
will arise (I'm probably the only one here who really used namespaces in
a whole PHP project, and saw how useful/harmful they are). If anyone
here have a better solution, I'm ready to implement and test it too.

Anyway a solution is needed before people do things like :

// Eeeeek-autoload, using eval() to create empty classes
function __autoload($class) {
$aClass = explode('::', $class);
if ($aClass[0] == 'virtual') {
$real_class = 'None';
switch($aClass[1]) {
case 'SQL': $real_class = 'MySQL'; break;
}

normal_autoload($real_class);
eval('class '.$class.' extends '.$real_class.' { }');
return;
}

normal_autoload($class);
}

(and it could be even worse, if for example overload is not only for one
namespace but for random class names).

By the way dynamic class lookup is something only runtime languages like
PHP can do, so don't try to compare this to anything found in
C++/Java/etc (or any other compiled language).


Best regards,
Mark Karpeles

Search Discussions

  • Mark at Sep 25, 2008 at 8:06 pm
    And just to answer to myself, here's a sample implementation of the
    __resolve() magic function.

    It's missing its second and third parameters and is still far from the
    final goal of this implementation, but at least it allows me to
    demonstrate a bit how this works. For example uses & interest, please
    see my mail from Thu, 25 Sep 2008 07:26:17 +0200.

    Patch against PHP 5.3.0alpha2:
    http://ookoo.org/svn/snip/php-5.3.0alpha2_resolve_class.patch

    Example of something which became possible (it just demonstrates that
    the whole thing works):
    http://ookoo.org/svn/snip/resolver_test.php

    Now I'll try to find out how I'll get the two last arguments (current
    namespace and use list) and try to make a proper patch out of this so it
    may have chances (?) to be looked at.


    The patch url points to a SVN and the file will be updated as soon as I
    improve the code.

    The name of the magic function isn't defined either, I guess calling it
    __resolveclass() would be better than __resolve(), but I was hoping to
    get some answers from the list.


    Mark

    Le jeudi 25 septembre 2008 à 07:26 +0200, Mark a écrit :
    Hi, [...]
    Best regards,
    Mark Karpeles

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupphp-internals @
categoriesphp
postedSep 25, '08 at 5:26a
activeSep 25, '08 at 8:06p
posts2
users1
websitephp.net

1 user in discussion

Mark: 2 posts

People

Translate

site design / logo © 2022 Grokbase