Hướng dẫn type callable php

Callbacks can be denoted by the callable type declaration.

Some functions like call_user_func[] or usort[] accept user-defined callback functions as a parameter. Callback functions can not only be simple functions, but also object methods, including static class methods.

Passing

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[].

A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1. Accessing protected and private methods from within a class is allowed.

Static class methods can also be passed without instantiating an object of that class by either, passing the class name instead of an object at index 0, or passing 'ClassName::methodName'.

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

Note:

As of PHP 8.1.0, anonymous functions can also be created using the first class callable syntax.

Generally, any object implementing __invoke[] can also be passed to a callback parameter.

Example #1 Callback function examples

Example #2 Callback example using a Closure

The above example will output:

Note:

Callbacks registered with functions such as call_user_func[] and call_user_func_array[] will not be called if there is an uncaught exception thrown in a previous callback.

andrewbessa at gmail dot com

10 years ago

You can also use the $this variable to specify a callback:

steve at mrclay dot org

10 years ago

Performance note: The callable type hint, like is_callable[], will trigger an autoload of the class if the value looks like a static method callback.

computrius at gmail dot com

8 years ago

When specifying a call back in array notation [ie. array[$this, "myfunc"] ] the method can be private if called from inside the class, but if you call it from outside you'll get a warning:



Output:
1
2
3
4

Warning: array_walk[] expects parameter 2 to be a valid callback, cannot access private method mc::walkIt[] in /in/tfh7f on line 22

Riikka K

7 years ago

A note on differences when calling callbacks as "variable functions" without the use of call_user_func[] [e.g. ""]:

- Using the name of a function as string has worked since at least 4.3.0
- Calling anonymous functions and invokable objects has worked since 5.3.0
- Using the array structure [$object, 'method'] has worked since 5.4.0

Note, however, that the following are not supported when calling callbacks as variable functions, even though they are supported by call_user_func[]:

- Calling static class methods via strings such as 'foo::doStuff'
- Calling parent method using the [$object, 'parent::method'] array structure

All of these cases are correctly recognized as callbacks by the 'callable' type hint, however. Thus, the following code will produce an error "Fatal error: Call to undefined function foo::doStuff[] in /tmp/code.php on line 4":



The code would work fine, if we replaced the '$callback[]' with 'call_user_func[$callback]' or if we used the array ['foo', 'doStuff'] as the callback instead.

edanschwartz at gmail dot com

7 years ago

You can use 'self::methodName' as a callable, but this is dangerous. Consider this example:



This results in an error:
Warning: class 'FunctionCaller' does not have a method 'someAwesomeMethod'.

For this reason you should always use the full class name:


I believe this is because there is no way for FunctionCaller to know that the string 'self' at one point referred to to `Foo`.

InvisibleSmiley

1 year ago

If you pass a callable method to a function with a callable type declaration, the error message is misleading:



Error message will be something like "Argument #1 [$c] must be of type callable, array given" while the actual problem here is only the visibility of method "foo". All you need to do is changing it to public [or use a different approach, e.g. with a Closure].

Yzmir Ramirez

8 years ago

> As of PHP 5.2.3, it is also possible to pass 'ClassName::methodName'

You can also use 'self::methodName'.  This works in PHP 5.2.12 for me.

mariano dot REMOVE dot perez dot rodriguez at gmail dot com

7 years ago

I needed a function that would determine the type of callable being passed, and, eventually,
normalized it to some extent. Here's what I came up with:



Hope someone else finds it useful.

bradyn at NOSPAM dot bradynpoulsen dot com

6 years ago

When trying to make a callable from a function name located in a namespace, you MUST give the fully qualified function name [regardless of the current namespace or use statements].

Daniel Klein

5 years ago

You can use "self::method_name", "static::method_name" and "parent::method_name" in callables:



Results:
Array
[
    [0] => 1: 42
    [1] => 2: 42
    [2] => 3: 42
]
Array
[
    [0] => 1: 42
    [1] => 2: 42
    [2] => 3: 42
]
Array
[
    [0] => 1: 123
    [1] => 2: 123
    [2] => 3: 123
]
Array
[
    [0] => 1: Zaphod Beeblebrox
    [1] => 2: Zaphod Beeblebrox
    [2] => 3: Zaphod Beeblebrox
]

"self::" uses the same class as the called method, "static::" uses the same class as the called class, and "parent::" [not shown] uses the parent class, or generates a warning if there is no parent.

pawel dot tadeusz dot niedzielski at gmail dot com

6 years ago

@edanschwartz at gmail dot com

You can use ::class property to always indicate the class you're in when using static methods:

whysteepy at gmail dot com

5 years ago

Another Appearance of Callbacks! Here is one way of them - methods of an instantiated object can be callable and implemented as variable functions without php's default functions that can call user-defined callback functions.

class Test {
    protected $items = array[];

    public function __construct[]
    {
        $this->items[] = array[$this, 'callBackOne'];
        $this->items[] = array[$this, 'callBackTwo'];
    }

    public function callBackOne[]
    {
        echo __METHOD__ . ' has been called as a callback.';
    }

    public function callBackTwo[]
    {
        echo __METHOD__ . ' has been called as a callback.';
    }

    public function getItems[]
    {
        return $this->items;
    }
}

$o = new Test[];
$itemLists = $o->getItems[];

foreach [$itemLists as $itemList] {

        // call each one as a variable function
        echo '

';
        print_r[$itemList[]];
        echo '
';
}

// Outputs the following
// Test::callBackOne has been called as a callback.

// Test::callBackTwo has been called as a callback.

chechomancr at hotmail dot com

7 months ago

In PHP >= 8.0 callIt function with optional parameters.


How to use:


Result: array [ 'information' => 'Hello world 2022' ]

chris dot rutledge at gmail dot com

3 years ago

Having read this line in the manual above,

"A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1. Accessing protected and private methods from within a class is allowed."

I decided to do some testing to see if I could access private methods using the call_user_func methods. Thankfully not, but for completeness here is my test which also covers using static and object contexts

Dan J

4 years ago

You can avoid repeating a long namespace for classes in callable arrays by making use of the "use" operator and the special "::class" constant.

Documentation of use operator:
//php.net/manual/en/language.namespaces.importing.php

Documentation of ::class constant:
//php.net/manual/en/language.oop5.constants.php

Chủ Đề