12

I'm trying to reference a private variable of an object from within a closure. The code below would seem to work, but it complains Fatal error: Cannot access self:: when no class scope is active in test.php on line 12 and Fatal error: Using $this when not in object context in test.php on line 20.

Any ideas how to accomplish the same results using a closure while keeping the variables private and without making helper functions (defeating the whole idea of a private variable).

class MyClass { static private $_var1; private $_var2; static function setVar1( $value ) { $closure = function () use ( $value ) { self::$_var1 = $value; }; $closure(); } function setVar2( $value ) { $closure = function () use ( $value ) { $this->_var2 = $value; }; $closure(); } } MyClass::setVar1( "hello" ); //doesn't work $myclass = new MyClass; $myclass->setVar2( "hello" ); //doesn't work 

3 Answers 3

14

Edit to note, this answer was originally meant for PHP5.3 and earlier, it's possible now. For current information, see this answer.


This is not directly possible. In particularly, closures have no associated scope, so they cannot access private and protected members.

You can, however, use references:

<?php class MyClass { static private $_var1; private $_var2; static function setVar1( $value ) { $field =& self::$_var1; $closure = function () use ( $value, &$field ) { $field = $value; }; $closure(); } function setVar2( $value ) { $field =& $this->_var2; $closure = function () use ( $value, &$field ) { $field = $value; }; $closure(); } } MyClass::setVar1( "hello" ); $myclass = new MyClass; $myclass->setVar2( "hello" ); 
Sign up to request clarification or add additional context in comments.

3 Comments

@Dave I was actually writing it before I read your answer. Anyway, +1 for you as a settlement :p
Heh. Speedy parallel development. Thanks for the +1, and returned in kind as you put far more effort in than I! :-)
You could also use Closure::bind as in my question here: stackoverflow.com/q/52701638/1163000
4

This is possible starting in PHP 5.4.0

class test { function testMe() { $test = new test; $func = function() use ($test) { $test->findMe(); // Can see protected method $test::findMeStatically(); // Can see static protected method }; $func(); return $func; } protected function findMe() { echo " [find Me] \n"; } protected static function findMeStatically() { echo " [find Me Statically] \n"; } } $test = new test; $func = $test->testMe(); $func(); // Can call from another context as long as // the closure was created in the proper context. 

1 Comment

Just to clarify, would that work also for private function findMe()?
2

Closures have no concept of $this or self -- they are not tied to objects in that way. This means that you would have to pass the variables through the use clause... something like:

$_var1 =& self::$_var1; $closure = function() use ($value, &$_var1) { $_var1 = $value; }; $_var2 =& $this->_var2; $closure = function() use ($value, &$_var2) { $_var2 = $value; }; 

I haven't tested the above code, but I believe it to be correct.

1 Comment

That's not correct, at least not in 5.4. See: php.net/manual/en/closure.bindto.php

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.