PHP: Hint Type - Difference between `Closure` and` Callable`

I noticed that I can use either of Closure or Callable as a type hint if we expect the callback function to complete. For example:

 function callFunc1(Closure $closure) { $closure(); } function callFunc2(Callable $callback) { $callback(); } $function = function() { echo 'Hello, World!'; }; callFunc1($function); // Hello, World! callFunc2($function); // Hello, World! 

Question:

What is the difference here? In other words, when to use Closure and when to use Callable OR do they serve the same purpose?

+63
php
Apr 19 '15 at 13:49 on
source share
3 answers

The difference is that Closure should be an anonymous function, where callable can also be a normal function.

You can see / check this with the example below, and you will see that you get an error message for the first:

 function callFunc1(Closure $closure) { $closure(); } function callFunc2(Callable $callback) { $callback(); } function xy() { echo 'Hello, World!'; } callFunc1("xy"); // Catchable fatal error: Argument 1 passed to callFunc1() must be an instance of Closure, string given callFunc2("xy"); // Hello, World! 

So, if you only want to introduce an anonymous hint function, use: Closure , and if you want to enable normal functions callable , use callable as a type hint.

+86
Apr 19 '15 at 13:56 on
source share

The main difference between the two is that closure is a class and a callable type.

callable type accepts anything that might be called :

 var_dump( is_callable('functionName'), is_callable([$myClass, 'methodName']), is_callable(function(){}) ); 

In case closure will accept only an anonymous function. Note that in PHP version 7.1 you can convert functions to closures as follows: Closure::fromCallable('functionName') .




Example:

 namespace foo{ class bar{ private $val = 10; function myCallable(callable $cb){$cb()} function myClosure(\Closure $cb){$cb()} // type hint must refer to global namespace } function func(){} $cb = function(){}; $fb = new bar; $fb->myCallable(function(){}); $fb->myCallable($cb); $fb->myCallable('func'); $fb->myClosure(function(){}); $fb->myClosure($cb); $fb->myClosure(\Closure::fromCallable('func')); $fb->myClosure('func'); # TypeError } 

So why use closure over callable ?

Strict because closure is an object that has some additional methods: call() , bind() and bindto() . They allow you to use a function declared outside the class and execute it as if it were inside the class.

 $inject = function($i){return $this->val * $i;}; $cb1 = Closure::bind($inject, $fb); $cb2 = $inject->bindTo($fb); echo $cb1->call($fb, 2); // 20 echo $cb2(3); // 30 

On the side note: the closure class cannot be extended as its final .

+17
Dec 02 '16 at 23:09
source share

It is worth noting that this will not work for PHP versions 5.3.21 - 5.3.29.

In any of these versions you will get output, for example:

Hello World! Allowable fatal error: argument 1 passed to callFunc2 () must be an instance> Callable, an instance of the Closure data, called in / in / kqeYD on line 16 and defined in / in / kqeYD on line 7

The process has completed with code 255.

You can try this using https://3v4l.org/kqeYD#v5321

Respectfully,

0
Dec 31 '15 at 20:34
source share



All Articles