views:

65

answers:

1

I've been asking a few questions on this topic recently, so I feel it appropriate to link up the associated question(s).

http://stackoverflow.com/questions/4054424/php-closures-and-implicit-global-variable-scope

I've got a set of classes that use closures as in the example below (keep in mind I quickly punched together this example for this thread) My question involves passing the $obj argument to the functions.

Does there exist any sort of magic variable (cough-$this-cough) that would permit me to access the object it's called from, instead of needing to declare a placeholder argument of $obj or whatever? Perhaps I've misread, but it appears the functionality I'm seeking has been removed, at least in the context of $this.

class Test{

    private $_color;
    protected $_children = array();

    public function __construct(Closure $function){
        $function($this);
    }

    public function create(Closure $function){
        return new self($function);
    }

    public function color($color){
        $this->_color = $color;
        return $this;
    }

    public function add(Closure $function){
        $this->_children[] = new Test($function);
        return $this;
    }

}

Test::create(function($obj){
    $obj->color('Red')
        ->add(function(){
             $obj->color('Green');
        })
        ->color('Blue');
    });

The only alternative I can see off-hand is storing an instance of each object at creation, and providing a function to return that instance as follows:

class Test{

    private $_color;
    private static $_instance;
    protected $_children = array();

    public function __construct(Closure $function){
        self::$_instance = $this;
        $function();
    }

    .
    .
    .

    public static function this(){
        return self::$_instance;
    }

}

Test::create(function(){
    Test::this()
        ->color('Red')
        ->add(function(){
            Test::this()
                ->color('Green');
        })
        ->color('Blue');
    });
+1  A: 

You should use the first version. Providing the class instance statically isn't really good (apart from singleton use.) Imagine that you have two instances. Then only the latter will be statically served. You couldn't do anything with the first.

Still even with your first approach there is a not unimportant limitation: You can only access public methods. There is a hacky workaround using Reflection around this. So, are you only using public methods?

Apart from that: You should not rely on the Closure class. This is only important for PHP's internal implementation and shouldn't be relied on. Better check that it is_callable.

nikic
Thanks **nikic**; Only the public methods are being called, so visibility is not a problem. I am aware of the unreliability of the `Closure` class, and will revert to something more permanent when the time comes, I just like the type-hinting it provides in the IDE I'm using.Regardless, there aren't any *magic* variables, or other tricks I could use to achieve this functionality inherently?
TomcatExodus
No, there aren't ;)
nikic
Thanks again **nikic** :)
TomcatExodus