How to use class methods as callbacks

PhpOopCallback

Php Problem Overview


I have a class with methods that I want to use as callbacks.
How can I pass them as arguments?

Class MyClass {
	
	public function myMethod() {
        // How should these be called?
		$this->processSomething(this->myCallback);
		$this->processSomething(self::myStaticCallback);
	}

	private function processSomething(callable $callback) {
		// Process something...
		$callback();
	}

	private function myCallback() {
		// Do something...
	}

	private static function myStaticCallback() {
	    // Do something...
	}	
	
}

Php Solutions


Solution 1 - Php

Check the callable manual to see all the different ways to pass a function as a callback. I copied that manual here and added some examples of each approach based on your scenario.

> Callable > ---


> - A PHP function is passed by its name as a string. Any built-in or user-defined function can be used, except language constructs such as: array(), echo, empty(), eval(), exit(), isset(), list(), print or unset().

  // Not applicable in your scenario
  $this->processSomething('some_global_php_function');

> - A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.

  // Only from inside the same class
  $this->processSomething([$this, 'myCallback']);
  $this->processSomething([$this, 'myStaticCallback']);
  // From either inside or outside the same class
  $myObject->processSomething([new MyClass(), 'myCallback']);
  $myObject->processSomething([new MyClass(), 'myStaticCallback']);

> - Static class methods can also be passed without instantiating an object of that class by passing the class name instead of an object at index 0.

  // Only from inside the same class
  $this->processSomething([__CLASS__, 'myStaticCallback']);
  // From either inside or outside the same class
  $myObject->processSomething(['\Namespace\MyClass', 'myStaticCallback']);
  $myObject->processSomething(['\Namespace\MyClass::myStaticCallback']); // PHP 5.2.3+
  $myObject->processSomething([MyClass::class, 'myStaticCallback']); // PHP 5.5.0+

> - Apart from common user-defined function, anonymous functions can also be passed to a callback parameter.

  // Not applicable in your scenario unless you modify the structure
  $this->processSomething(function() {
      // process something directly here...
  });

Solution 2 - Php

Since 5.3 there is a more elegant way you can write it, I'm still trying to find out if it can be reduced more

$this->processSomething(function() {
	$this->myCallback();
});

Solution 3 - Php

You can also to use call_user_func() to specify a callback:

public function myMethod() {

    call_user_func(array($this, 'myCallback'));
}

private function myCallback() {
    // do something...
}

Solution 4 - Php

As of PHP 8.1, we now have first-class callables. They use the syntax $callable = functionName(...).

You can use the new syntax to create callable class methods.

Class MyClass {
    
    public function myMethod() {
        // first-class callables
        $this->processSomething($this->myCallback(...));
        $this->processSomething(self::myStaticCallback(...));
    }

    private function processSomething(callable $callback) {
        // Process something...
        $callback();
    }

    private function myCallback() {
        // Do something...
    }

    private static function myStaticCallback() {
        // Do something...
    }   
    
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSmxCdeView Question on Stackoverflow
Solution 1 - PhpMikOView Answer on Stackoverflow
Solution 2 - PhpBankzillaView Answer on Stackoverflow
Solution 3 - PhpGeovani SantosView Answer on Stackoverflow
Solution 4 - PhpDharmanView Answer on Stackoverflow