简体   繁体   中英

Pass class method to a closure in PHP (similar to JS)

In Javascript you can do this:

// Define a function
function logIt(a, b) { console.log(a, b); }

function somethingElse() {
    // Store it in a variable
    var theLog = logIt; 
    // Call it somewhere else *as the variable-name*
    asyncCall(function() { theLog(1, 2); });
}

What I'd like to do in PHP is this:

class A
{
    // Define a simple class method
    protected function echoIt($a, $b) {
        echo $a, $b;
    }

    public function doSomething(array $things) {
        $theEchoFunction = $this->echoIt; // save it for the next line

        // Get into a closure and pass the method as a variable
        array_map(function($thing) use ($theEchoFunction) { // <-- this is the bit I'd like to do
            // Call the function directly from the variable
            $theEchoFunction($thing[0], $thing[1]);
        }, $things);
    }
}

I know that it's easy enough to just do $that = $this; then pass $that through to the closure, but that means I can't access $that->echoIt because it's protected. Is it possible to send the method itself to the closure?

This question could actually be the X/Y problem I guess. What I want to do is call the protected method from inside the closure. I'd like to just pass the method so that the closure doesn't need to know that the class has an echoIt method.

Specifically, this will do just fine* (in PHP as in Javascript):

class A
{

    protected function echoIt($a, $b) {
        echo $a, $b;
    }

    public function doSomething(array $things) {
        array_map(function ($thing) {
            $this->echoIt($thing[0], $thing[1]);
        }, $things);
    }

}

Assuming that is just a test setup and you do need to pass the callback around in a variable, the way to do that is with a callable pseudo type :

class A
{

    protected function echoIt($a, $b) {
        echo $a, $b;
    }

    public function doSomething(array $things) {
        $callback = [$this, 'echoIt'];
        array_map(function ($thing) use ($callback) {
            $callback($thing[0], $thing[1]);
        }, $things);
    }

}

* Since PHP 5.4.

class Test
{
    protected function echoIt($a, $b) {
        echo $a, $b;
    }

    public function doSomething(array $things) {
        $theEchoFunction = function($a, $b) {
            return $this->echoIt($a, $b);
        };

        array_map(function($thing) use ($theEchoFunction) {
            $theEchoFunction($thing[0], $thing[1]);
        }, $things);
    }
}

$test = new Test();
$test->doSomething(["1", "2"]);

Result

12

This works for me, I don't know if it works as you expected. But to assign the method to a variable, you'd need to make the variable callable. Thus made me think that you can create an anonymous function that is wrapper over the protected method. Then you pass that function to the closure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM