Accessing private variables from within a closure

2019-01-26 07:04发布

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条回答
Juvenile、少年°
2楼-- · 2019-01-26 07:11

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.
查看更多
欢心
3楼-- · 2019-01-26 07:20

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.

查看更多
疯言疯语
4楼-- · 2019-01-26 07:30

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" );
查看更多
登录 后发表回答