How to Implement a Callback in PHP

How do I implement a callback in PHP?

The manual uses the terms "callback" and "callable" interchangeably, however, "callback" traditionally refers to a string or array value that acts like a function pointer, referencing a function or class method for future invocation. This has allowed some elements of functional programming since PHP 4. The flavors are:

$cb1 = 'someGlobalFunction';
$cb2 = ['ClassName', 'someStaticMethod'];
$cb3 = [$object, 'somePublicMethod'];

// this syntax is callable since PHP 5.2.3 but a string containing it
// cannot be called directly
$cb2 = 'ClassName::someStaticMethod';
$cb2(); // fatal error

// legacy syntax for PHP 4
$cb3 = array(&$object, 'somePublicMethod');

This is a safe way to use callable values in general:

if (is_callable($cb2)) {
// Autoloading will be invoked to load the class "ClassName" if it's not
// yet defined, and PHP will check that the class has a method
// "someStaticMethod". Note that is_callable() will NOT verify that the
// method can safely be executed in static context.

$returnValue = call_user_func($cb2, $arg1, $arg2);
}

Modern PHP versions allow the first three formats above to be invoked directly as $cb(). call_user_func and call_user_func_array support all the above.

See: http://php.net/manual/en/language.types.callable.php

Notes/Caveats:

  1. If the function/class is namespaced, the string must contain the fully-qualified name. E.g. ['Vendor\Package\Foo', 'method']
  2. call_user_func does not support passing non-objects by reference, so you can either use call_user_func_array or, in later PHP versions, save the callback to a var and use the direct syntax: $cb();
  3. Objects with an __invoke() method (including anonymous functions) fall under the category "callable" and can be used the same way, but I personally don't associate these with the legacy "callback" term.
  4. The legacy create_function() creates a global function and returns its name. It's a wrapper for eval() and anonymous functions should be used instead.

How to use class methods as callbacks

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...
});

How to pass argument in callback function in php?

Use use. :D

With the use clause, you can import variables from the parent scope into the scope of the function.

public function GetOne($id){
$method = __METHOD__;
$post = null;


$post = $this->CacheManager($method, function() use ($id) {
return DB::select("select * from posts where id = ?", [$id]);
});

return $post;
}

Just a side note. Since it looks you are building a caching mechanism, you will need to include the ID in the cache as well. Currently you only check by $method, but for each id you will probably have a different cache entry which may or may not exist. So I think in your function you need to do something like the line below to make the cache key more unique. I would also call the parameter $method something like $cacheKey instead, since to the cache it shouldn't be linked to a method name per se.

$method = __METHOD__ . ";$id";

Update for PHP 7.4: arrow functions

The RFC for arrow functions (AKA 'short closures') has passed voting.

With these you don't specify the parameters you want to close in, because they can only have a single expression anyway, so any expression/value they use can (and will) be taken from the parent function scope.

Since in this case the anonymous function just has a single statement, it can be rewritten into an arrow function. The call to the cache manager will then look like this:

public function GetOne($id){
$method = __METHOD__;
$post = null;

$post = $this->CacheManager($method, fn() => DB::select("select * from posts where id = ?", [$id]));

return $post;
}

pass a callback WITH arguments in PHP


$that = $this;

$wrapper = function() use($that) {
return $that->my_function_name('arg1', 'arg2');
};

What is a callback function and how do I use it with OOP

Here's a basic callback function example:

<?php

function thisFuncTakesACallback($callbackFunc)
{
echo "I'm going to call $callbackFunc!<br />";
$callbackFunc();
}

function thisFuncGetsCalled()
{
echo "I'm a callback function!<br />";
}

thisFuncTakesACallback( 'thisFuncGetsCalled' );
?>

You can call a function that has its name stored in a variable like this: $variable().

So, in the above example, we pass the name of the thisFuncGetsCalled function to thisFuncTakesACallback() which then calls the function passed in.



Related Topics



Leave a reply



Submit