Perbedaan utama di antara mereka adalah bahwa a closureadalah kelas dan callablesatu jenis .
Itu callable Tipe menerima apa pun yang bisa disebut :
var_dump(
is_callable('functionName'),
is_callable([$myClass, 'methodName']),
is_callable(function(){})
);
Di mana closureakan hanyamenerima fungsi anonim. Perhatikan bahwa dalam PHP versi 7.1 Anda dapat mengkonversi fungsi untuk penutupan seperti:
Closure::fromCallable('functionName').
Contoh:
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
}
Jadi mengapa menggunakan closureover callable?
Ketatnya karena closuremerupakan objek yang memiliki beberapa metode tambahan: call(), bind()danbindto() . Mereka memungkinkan Anda untuk menggunakan fungsi yang dideklarasikan di luar kelas dan menjalankannya seolah-olah itu di dalam kelas.
$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
Anda tidak ingin memanggil metode pada fungsi normal karena itu akan memunculkan kesalahan fatal. Jadi untuk menghindari itu Anda harus menulis sesuatu seperti:
if($cb instanceof \Closure){}
Untuk melakukan ini, periksa setiap saat tidak ada gunanya. Jadi jika Anda ingin menggunakan metode-metode tersebut nyatakan bahwa argumennya adalah aclosure . Kalau tidak, gunakan saja yang normal callback. Cara ini; Kesalahan muncul pada pemanggilan fungsi alih-alih kode Anda sehingga membuatnya lebih mudah untuk didiagnosis.
Di samping catatan: The closureclass tidak dapat diperpanjang sebagai yang akhir .
["Foo", "bar"]untukFoo::baratau[$foo, "bar"]untuk$foo->bar.