PHP closure return multiple functions

233 Views Asked by At

I'm trying to achieve almost similar things/properties of closure in PHP which is available in JS.

For example

function createGreeter($who) {
    return function(){
        function hello() use ($who) {
            echo "Hi $who";
        }

        function bye() use($who){
            echo "Bye $who";
        }
    };
} 

I know my syntax is incorrect, this what I'm trying to achieve.

What I've done so far is.

function createGreeter() {
    $hi = "hi how are you.";
    $bye = "bye wish you luck.";
    return function($operation) use ($hi, $bye){
        if ($operation == "a") return $hi;
        elseif ($operation == "b") return $bye;
    };
}
$op = createGreeter();
echo $op("a"); #prints hi how are you.
echo $op("b"); #prints bye wish you luck.

Please look does PHP allows us to do this.

2

There are 2 best solutions below

3
Nigel Ren On BEST ANSWER

You could return an anonymous class which is created with the $who and then has methods which output the relevant message...

function createGreeter($who) {
    return new class($who){
        private $who;
        public function __construct( $who ) {
            $this->who = $who;
        }
        function hello() {
            echo "Hi {$this->who}";
        }

        function bye(){
            echo "Bye {$this->who}";
        }
    };
} 
$op = createGreeter("me");
echo $op->hello();    // Hi me
echo $op->bye();      // Bye me
0
Nigel Ren On

Decided to post as a new answer as it's a completely different solution. This follow the idea of creating private methods using closures (as linked to by OP in comment to my other answer - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Emulating_private_methods_with_closures).

This also draws on deceeze's comments on the original question, but casting the array to an object to more closely reflect the reference as being an object rather than an array...

function createGreeter($who) {
    return (object)
    [ "Hello" => function() use ($who) {
        echo "Hello {$who}";
    },
    "Goodbye" => function() use ($who) {
        echo "Goodbye {$who}";
    }];
} 
$op = createGreeter("me");
($op->Hello)();
($op->Goodbye)();

The ()'s around the methods are needed as it is a closure and not an actual method.

This gives...

Hello meGoodbye me