2

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

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 Answer 1

1

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?

At one point, Closure was considered an implementation detail and wasn't to be relied on. This is no longer the case; Closure is the documented type of anonymous functions.

Sign up to request clarification or add additional context in comments.

1 Comment

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?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.