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 个注释

13
igorchernin at yahoo dot com
7 年前
看起来“fromCallable”的结果与原始的 Lambda 函数的行为略有不同。

类 A {
私有 $name;
公共函数 __construct($name)
{
$this->name = $name;
}
}

// 测试可调用对象
函数 getName()
{
返回 $this->name;
}
$bob = 新的 A("Bob");

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

// 这将检索:未捕获的错误:无法访问私有属性 A::$name
$result = $cl1();
回显 $result;

// 但对于 Lambda 函数
$cl2 = 函数() {
返回 $this->name;
};
$cl2 = $cl2->bindTo($bob, 'A');
$result = $cl2();

// 这将打印 Bob
回显 $result;
7
4-lom at live dot de
6 年前
遗憾的是,您的比较不正确。

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

// 最有可能的是这个
$cl2 = 函数() {
返回 call_user_func_array("getName", func_get_args());
};
$cl2 = $cl2->bindTo($bob, 'A');

执行一个或另一个闭包应该会导致您已经发布的相同访问冲突错误。

----
一个简单的 PHP 7.0 polyfill 可以这样写
----

命名空间 YourPackage;

/**
* 类 Closure
*
* @参见 \Closure
*/
类 Closure
{
/**
* @参见 \Closure::fromCallable()
* @参数 callable $callable
* @返回 \Closure
*/
公共静态函数 fromCallable(callable $callable)
{
// 如果我们有本地版本,让我们使用本地版本!
如果(method_exists(\Closure::class, 'fromCallable')) {
返回 \Closure::fromCallable($callable);
}

返回函数 () 使用 ($callable) {
返回 call_user_func_array($callable, func_get_args());
};
}
}
4
nakerlund at gmail dot com
6 年前
我有两点

可以使用 Closure::fromCallable 将私有/受保护的方法转换为闭包并在类外部使用它们。

如果作为字符串提供,Closure::fromCallable 接受使用关键字 static 的延迟动态绑定。

下面的代码演示了如何在类外部的函数中将私有静态方法用作回调。

<?php
function myCustomMapper ( Callable $callable, string $str ): string {
return
join(' ', array_map( $callable, explode(' ', $str) ) );
}

class
MyClass {

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

}

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