PHP Conference Japan 2024

Closure::fromCallable

(PHP 7 >= 7.1.0)

Closure::fromCallable將可呼叫物件轉換為閉包

說明

public static Closure::fromCallable(callable $callback): Closure

使用目前的範圍,從給定的 callback 建立並返回一個新的 匿名函式。這個方法會檢查 callback 在目前的範圍內是否可呼叫,如果不是,則會拋出 TypeError 例外。

注意:

自 PHP 8.1.0 起,一流可呼叫語法 與此方法具有相同的語義。

參數

callback

要轉換的可呼叫物件。

回傳值

返回新建立的 Closure 物件,如果 callback 在目前作用域中不可呼叫,則拋出 TypeError

新增註解

使用者貢獻的註解 3 則註解

igorchernin at yahoo dot com
7 年前
“fromCallable” 的結果似乎與原始的 Lambda 函式行為略有不同。

class A {
private $name;
public function __construct($name)
{
$this->name = $name;
}
}

// 測試可呼叫物件
function getName()
{
return $this->name;
}
$bob = new A("Bob");

$cl1 = Closure::fromCallable("getName");
$cl1 = $cl1->bindTo($bob, 'A');

//這將會收到:Uncaught Error: Cannot access private property A::$name
$result = $cl1();
echo $result;

//但對於 Lambda 函式
$cl2 = function() {
return $this->name;
};
$cl2 = $cl2->bindTo($bob, 'A');
$result = $cl2();

// 這將會印出 Bob
echo $result;
4-lom at live dot de
6 年前
遺憾的是,您的比較不正確。

// 等同於
$cl1 = Closure::fromCallable("getName");
$cl1 = $cl1->bindTo($bob, 'A');

// 最有可能是這樣
$cl2 = function() {
return call_user_func_array("getName", func_get_args());
};
$cl2 = $cl2->bindTo($bob, 'A');

執行其中一個 Closure 應該會產生您已發布的相同的存取違規錯誤。

----
一個簡單的 PHP 7.0 polyfill 範例如下
----

namespace YourPackage;

/**
* Class Closure
*
* @see \Closure
*/
class Closure
{
/**
* @see \Closure::fromCallable()
* @param callable $callable
* @return \Closure
*/
public static function fromCallable(callable $callable)
{
// 如果我們有原生方法,就使用原生方法!
if(method_exists(\Closure::class, 'fromCallable')) {
return \Closure::fromCallable($callable);
}

return function () use ($callable) {
return call_user_func_array($callable, func_get_args());
};
}
}
nakerlund at gmail dot com
6 年前
我有兩點要說明

可以使用 Closure::fromCallable 將私有/保護方法轉換為閉包,並在類別外部使用它們。

如果以字串形式提供,Closure::fromCallable 接受使用關鍵字 static 的後期動態綁定。

我下面的程式碼示範了如何在類別外部的函式中使用私有靜態方法作為回呼。

<?php
函式 myCustomMapper ( Callable $callable, 字串 $str ): 字串 {
return
implode(' ', array_map( $callable, explode(' ', $str) ) );
}

類別
MyClass {

public static function
mapUCFirst ( 字串 $str ): 字串 {
$privateMethod = 'static::mapper';
$mapper = Closure::fromCallable( $privateMethod );
return
myCustomMapper( $mapper, $str );
}
private static function
mapper ( 字串 $str ): 字串 {
return
ucfirst( $str );
}

}

echo
MyClass::mapUCFirst('four little uncapitalized words');
// 輸出:Four Little Uncapitalized Words
?>
To Top