Search code examples
phpmethodsfunctional-programminganonymous-functionbound-variable

How to bind returned function local variable to method parameter?


I would like to get the following PHP code to work. The part that is not working is that the inner variable $greetingCount (the returned function's local variable) is not binding to the outer variable $greetingCount (the method parameter variable).

class Greetings {

  public static function getRepeatGreeterFunc($greetingCount) {

    $repeatGreeter = function($greeting) {

      // I want $greetingCount to bind to the outer $greetingCount here.
      // If 4 is passed to getRepeatGreeterFunc, then it should be 4 here,
      // so that what I get is a function that prints the greeting 4 times.

      for ($i = 0; $i < $greetingCount; $i++) {

        echo $greeting . "\n";

      }

    };

    return $repeatGreeter;

  }

  public function greet() {

    $repeatGreeter = self::getRepeatGreeterFunc(4);
    call_user_func($repeatGreeter, "HELLO");

  }

}

$greetings = new Greetings();
$greetings->greet();

// OUTPUT:

none

// EXPECTED OUTPUT:

HELLO
HELLO
HELLO
HELLO

NOTE: I would like a solution that also works when the static method is made nonstatic, otherwise two different solutions for these two cases will do.


Solution

  • The answer is to make use of the PHP use keyword:

    class Greetings {
    
      public static function getRepeatGreeterFunc($greetingCount) {
    
        $repeatGreeter = function($greeting) use ($greetingCount) {
    
          // I want $greetingCount to bind to the outer $greetingCount here.
          // If 4 is passed to getRepeatGreeterFunc, then it should be 4 here,
          // so that what I get is a function that prints the greeting 4 times.
    
          for ($i = 0; $i < $greetingCount; $i++) {
    
            echo $greeting . "\n";
    
          }
    
        };
    
        return $repeatGreeter;
    
      }
    
      public function greet() {
    
        $repeatGreeter = self::getRepeatGreeterFunc(4);
        call_user_func($repeatGreeter, "HELLO");
    
      }
    
    }
    
    $greetings = new Greetings();
    $greetings->greet();
    

    OUTPUT:

    HELLO
    HELLO
    HELLO
    HELLO