View Single Post
Old 01-07-2009, 12:47 AM   #13 (permalink)
sketchMedia
The Prestige
Advanced Programmer Top Contributor Good Samaritan 
 
sketchMedia's Avatar
 
Join Date: Oct 2007
Location: Manchester, UK
Posts: 854
Thanks: 32
sketchMedia is on a distinguished road
Default

Quote:
If i am honest with you I dont need any registry etc if its possible. I just really need to make that global
But it is accessible globally via the static method of the factory (which kind of behaves like a registry, apart from it adds non-existent objects automatically as opposed to the registry above (my example) that requires you to at start up load or 'register' objects to the array.

There is no way to make a variable, such as '$app' fully accessible like that (i.e. automatically available in other scopes) as far as im aware anyway, it will work great until you enter into another scope, then it wont be accessible (as you are no longer in the global scope).
We can however use the global keyword to 'import' any variables defined in the global scope into our current scope.

An example:
PHP Code:
//Some init file --- bootstrap.php
$app = new stdClass();
$app->test "A test message";

//'app' defined in 'global' scope

//implementation file --- driver.php
function aSimpleFunction()
{
    
//We are now in the aSimpleFunction's scope, therefore this will fail as 'app' doesn't exist in this scope
    
echo $app->test;
}
//however! this still works as we are now back in the global scope and 'app' is once again in our 'sight':
echo $app->test;

aSimpleFunction(); 
If we put 'global' in there:
PHP Code:
$app = new stdClass();
$app->test "A test message";

function 
aSimpleFunction()
{
    global 
$app;
    
//we can now see app again!!!
    
echo $app->test;
}
aSimpleFunction(); 
But however such variables are considered bad practice for many reasons and frowned upon by many (myself included). This however (as with many things in programming) opens another heated debate which I wont be going into now I don't have the energy.

I'm not sure if I understand your implementation of a singleton (or indeed most of it, seems very complex for a relatively simple problem in my opinion).

I approve of the use of a factory method; as it allows you to access system objects without worrying about whether the class has been included (if its implemented to include the file needed) and/or pushed on the the system object array (i.e. registry), but is there anything stopping me doing this?:
PHP Code:
$newApp = new class(); 
Sorry if I have mis-interpreted your code, but I'm tired and my right eye seems to be twitching? which is either down to the fact that i have had FAR far too much coffee today, or indeed not enough! now there's a conumdrum. Its getting rather annoying actually; not that's any excuse mind you .

Anywho.....

A singleton object is an object that can be created only once, there shouldn't really be an external factory/registry implementation involved in order to make an object singleton. This is a classic singleton implementation:

PHP Code:
class someRandomClass
{
    private static 
$_pSelf;
//you could do this more elegantly than induce a fatal error but I cba ;)
    
private function __construct() {}
    private function 
__clone() {}

    public function 
getInstance()
    {
        if(!
self::$_pSelf instanceof self)
        {
            
self::$_pSelf = new self();
        }
        return 
self::$_pSelf;
    }
}

$obj someRandomClass::getInstance(); //works
$obj = new someRandomClass//will fail
$obj2 = clone $obj//will fail 
you can call :
PHP Code:
$obj someRandomClass::getInstance(); 
as many times as your server or indeed patience will alow and you will always end up with the same instantiation of that particular class and creating a new one is simply not possible via 'new' keyword or even cloning the existing object returned by 'getInstance' thus making it singleton. The added bonus to this of course (and used to good effect in the factory implementation by Wildhoney) is that it is (once included) accessible globally regardless of the scope, by just typing this:
PHP Code:
$obj someRandomClass::getInstance(); 
For what its worth, if you dont like the 'factory::accessor('classname')' syntax you may as well do this:
PHP Code:

function factory($szObject)
{
    return 
TalkPHP_Factory::getInstance()->$szObject();   
}

echo 
factory('TalkPHP_Hello')->getText();
echo 
factory('TalkPHP_Goodbye')->getText(); 
A little pointless and one more function call than there should be but it basically provides the same basic api and behaviours as your solution.

BTW, a few errors in your code (well notices if you read as PHP would) Wildhoney, a few static properties called in an objective context. Nothing however to scream about
PHP Code:
    if (!isset($this->m_aInstances[$szClass]))
        {
            
$this->m_aInstances[$szClass] = new $szClass();
        }
        
        return 
$this->m_aInstances[$szClass]; 
should be
PHP Code:
    if (!isset(self::$m_aInstances[$szClass]))
        {
            
self::$m_aInstances[$szClass] = new $szClass();
        }
        
        return 
self::$m_aInstances[$szClass]; 
__________________
mysql> SELECT * FROM `users` WHERE `users`.`clue` > 0;
Empty set (0.00 sec)
sketchMedia is offline  
Reply With Quote
The Following 2 Users Say Thank You to sketchMedia For This Useful Post:
Scottymeuk (01-07-2009), Wildhoney (01-07-2009)