Guilherme Blanco’s Blog: register_superglobal(”NAME”);

Some time ago I spoke with Derick Rethans about the possibility to create a function called “register_superglobal”.
Currently, we deal with a lot of interesting situations of web applications, and some really interesting are the superglobals variables. Seems there will be a change in superglobals soon and that’s why I decided to post about it here.

When you build an application in PHP, and you want to access the Database class instance in a method, you have 2 possibilities:

  • Pass the global variable, like globals $db or accessing via $GLOBALS[’db’]
  • Using a singleton pattern, and accessing $db = & Database::getInstance(); (PHP5 does not require the ref signal anymore)

While the last one seems to be the best solution, you have a problem of generating classes to each Database connection. So, if you are dealing with 3 Database connections, you will have to modify the singleton accessor to support multiple named instances.

Together with Databases, we have to apply the same idea of Configuration class instances, I18n class instances and some other widgets that you usually play in your application and have to access inside class’ methods.

My idea was to enable the possibility to register a superglobal variable, and access it inside the method like a _POST, _GET variables. To support this, I imagined something like:

$DB = & Database::getConnection($postgreDsn);
register_superglobal("DB");

And after that I could use the $DB variable as a superglobal, without taking care of the scope, since this is an instance that is used in almost all Model classes and some others. Currently, to do this, I define an Aspect which Advice make the “superglobals” definitions, by calling the singleton patterns of each component. The solution is good, since Transparent PHP AOP does this perfectly, but it’s not the ideal solution and I think PHP should support it.

I decided to talk with Derick about it. After 20 minutes of explanation, he enjoyed the idea and decided to talk with other PHP maintainers. I don’t remember who said that it was impossible, since the PHP structure makes a CV checking internally. Marcus suggested to use singleton and after the idea being explained, he said to use a class with static properties to solve this.
A little bit sad, I accepted the idea to hack another time and figure out a PHP solution to it. I tried the Marcus’ suggestion. After some code written, I checked that it is impossible to store an instance of a class in a static variable. So, this is impossible:

class Env {
static public $lang = new I18n("pt-br");
}

Back to the Factory theory. Here is the approach:

class Env {
function & lang() {
return I18n::load("pt-br");
}
}

Remember that load is the singleton modified to support multiple named instances.
And now we can use just like a static var… Env::lang()->someMethod(); Still not a nice solution.
So, it is time to think in another solution. Do you have one?
PS: With the new modifications of PHP core, maybe now it is possible to add the function I mentioned to core. If I have any information, I’ll post here.

PS2: Sean Coates remembered about the runkit extension, that enables the possibility to add superglobals variables via php.ini file. My idea is a much more powerful solution, via a function call, enabling to shared hosting users to build clearly applications, since most of them do not have access to php.ini file.

    11 Responses to “register_superglobal(”name”);”

  1. Alex Says:
    We use the singleton pattern a lot. And we implement it using a “normal” global, most of the time.

    Class DB{
    function instance(){
    global $dbinstance;
    if($dbinstance==null){
    $dbinstance=new DB();
    }
    return $dbinstance;
    }
    }

  2. PHPDeveloper.org Says:
    Guilherme Blanco’s Blog: register_superglobal(”name”);…

  3. Sean Coates Says:
    Check out runkit:
    http://php.net/runkit#ini.runkit.superglobal

    S

  4. guilhermeblanco Says:
    Hi Sean!

    The runkit enables you to predefine superglobals, but not at run-time. If you are running a shared hosting without privileges to change php.ini file, forget your solution.
    The idea is to enable a consistent, simple and powerful possibility to all PHP developers. =)

    I’ll update the post to describe this. I forgot to mention.

    Thanks

  5. stefan Says:
    And what about the Registry? I’ve seen this come by a few times in my work as well as in my hobby work and it’s a great way of having global “variables”. The Zend Framework has also implemented this: http://framework.zend.com/manual/en/zend.register.html and http://framework.zend.com/manual/en/zend.registry.html

    Basically, you have a seperate Registry class (or in this case, it’s put in the global Zend class) with two static functions: A setter and a getter. Depending on your wishes, you could either have the setter overwrite a previous value, or error out if you want the values to be constant.

    I think setting your own superglobals is, like using the ‘global’ operator in functions, a bit of a dirty solution, where you can have a clean OO solution.

  6. guilhermeblanco Says:
    Hi Stefan!

    This is my second way of code. I usually implement the Aspect approach, since this works well for me.
    If I’ll not use AOP, I implement a Registry class to do it.

    I uploaded a simple version of my Registry class if interested: http://blog.bisna.com/files/class.Registry.phps

  7. JackyMooll Says:
    Who can help me with .httpaccess ?
    where i can fined full information about .httpaccess file syntaxis?
  8. Sara Golemon Says:
    Runtime definition of superglobals will simply never* work because superglobals are resolved at compile time. Runtime comes after compile time. Short version: Chicken ->Egg.

    As to using runkit, it does allow specifying in a PERDIR context which means you can specify superglobals in an .htaccess file, you don’t need access to the system-wide php.ini (but you do need to convince your hoster to install runkit — which is a bigger hurdle).

    With regard to the article you linked to on zend devzone, that won’t help autoglobal registration at all. It only deals with how the executor handles the physical fetch.

    * - Well, okay, you could theoretically register superglobals for use in future include files, but that starts introducing inconsistencies…

  9. guilhermeblanco Says:
    Hello Sara!

    You’re one of the greatest people around PHP and I really enjoy your effort to make it a better language!

    I’ve been suggested exactly the same thing you mentioned about runkit yesterday. But, as you mentioned, it’s hard to convince hosters.

    *about devzone article* hmm, thanks for the information!

    During my compiler’s home works, I remembered to allow this possibility via a hash table. Since that was only for a class, no speed was being measured.
    When the variable was registered, it enters in the hash table and when I tried any statement that relates to a variable, I checked for local declaration and if not exists, I checked for hash table to look for a superglobal. if yes, I retrieve the variable from GLOBALS. That was… an interesting approach, but maybe not viable for PHP. My homework was a Krakatoa (portion of Java) => C compiler.

    I did this suggestion with the idea to solve code replication you usually see in scripts. I hope in a future you list this suggestion in a core change. =)

    Ah… I almost forgot: Keep the greatest work you and PHP maintainers do.

    Thanks

  10. Sara Golemon Says:
    Autoglobals could definitely be redesigned to work as you suggest, but we’d lose on performance having to do that extra work. Right now, there’s no performance difference between an autoglobal variable, a static variable, and a normal local variable during runtime. Making the resolution of autoglobals happen at runtime would double the work done when they’re fetched and that’s just….. not acceptable for PHP.

    Anyway, ideas are always a good thing, even when they don’t pan out. Don’t let this discourage you! :)

  11. guilhermeblanco Says:
    Sara,

    I understood that autoglobals are not viable to be changed, but the idea is a little bit different from what you imagined.

    The perfect behavior should be (inside a function), if a variable does not exist, try to access a global (without doing via $GLOBALS or global). If it doesn’t exist in the second try, then throw a fatal error. With this, you do not need to think in superglobal variable or anything else.
    Maybe this suggestion is currently too much difficult to achieve.

    The workaround can be done using normal variables. But, as I mentioned before, when the statement uses a variable, it checks for the local variables declarations hash table; the idea is different here… if the variable does not exist in local, look in the hash table I mentioned (which stores the subscribed variables to behavior like superglobal) and, if found, grab the variable from the global variable declarations hash table.

    As you can see, there will be only one performance impact (in normal variable), doing a hash table checking. You do not need to change autoglobal or static variables. In an average system, the needed time to do this checking will be an advantage than the currently best approach (Registry). You lose in one side, but receive more in the other.

    PS: I really need to separate some spare time to study the internal structure of PHP. =)

source: http://blog.bisna.com/archives/32