有收获的话请加颗小星星,没有收获的话可以 反对 没有帮助 举报三连

  • 示例代码
  • 本文地址
  • 本人能力有限,如遇到什么不对的地方还望指出修正,谢谢
  • 所有栗子的输出都使用symfony/var-dumpe美化了

匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。

匿名函数目前是通过 Closure 类来实现的。

一、栗子 1 用作于回调

$rs = preg_replace_callback('/-([a-z])/', function ($match) {
    return strtoupper($match[1]);
}, 'hello-world');

dump($rs); // “helloWorld”

复制代码

二、栗子 2 用作于变量赋值

$greet = function ($name) {
    dump($name);
};

dump($greet instanceof Closure); // true
$greet(‘PHP’); // “PHP”

复制代码

三、栗子 3 从父作用域继承变量

$message = 'hello';
$example = function () use ($message) {
    dump($message);
};
dump($example instanceof Closure); // true
$example(); // "hello"
复制代码

四、栗子 4 的前提条件,简单理解call_user_func_array()call_user_func()方法

1. call_user_func — 把第一个参数作为回调函数调用

function call_user_func (function, ...parameter){}

该方法接收多个参数,第一个就是回调函数,可以是普通函数,也可以是闭包函数,后面的多个参数都是作为函数回调使用

$rs = call_user_func(function (...$params) {
    return func_get_args();
}, 1, 2, 3);
dump($rs); // [1,2,3]
复制代码

2. call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数

function call_user_func_array (function, arrayparam_arr){}

该方法接收 2 个参数,第一个就是回调函数,可以是普通函数,也可以是闭包函数,后面的数组参数都是作为函数回调使用

$rs = call_user_func_array(function (array $params) {
    return func_get_args();
}, [1, 2, 3]);
dump($rs); // [1,2,3]
复制代码

五、栗子 4 绑定闭包在指定对象

楼主见解是将方法绑定到指定类上,使得方法也可以使用类的属性和方法,非常适合配合__call()魔术方法和call_user_func_array方法一起使用

1. Closure::bindTo — 复制当前闭包对象,绑定指定的 $this 对象和类作用域。

function bindTo(newthis,newscope = 'static'){}

<?php
namespace PHP\Demo\Closure;

class ClosureBindTo
{
public function __call($name, $arguments)
{
if (count($arguments) > 1 && $arguments[0] instanceof \Closure) {
return call_user_func_array($arguments[0]->bindTo($this), array_slice($arguments, 1));
}
throw new \InvalidArgumentException(“没有这个方法”);
}
}

// 测试
public function testClosureBindTo()
{
$obj = new ClosureBindTo();
$this->assertEquals(2, $obj->add(function (array $params) {
return ++$params[0];
}, [1]));

<span class="hljs-comment">// 测试同一个实例</span>
$newObj = $obj-&gt;test(<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(array $params)</span></span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>;
}, [<span class="hljs-number">1</span>]);
<span class="hljs-keyword">$this</span>-&gt;assertTrue($newObj <span class="hljs-keyword">instanceof</span> $obj);

}

复制代码

2. Closure::bind — 复制一个闭包,绑定指定的 $this 对象和类作用域。

static function bind(Closure closure,newthis, $newscope = 'static'){}

bind 函数是 bindTo 的静态表示

<?php
namespace PHP\Demo\Closure;

class ClosureBind
{
private $methods = [];

<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addMethod</span><span class="hljs-params">(string $name, \Closure $callback)</span>
</span>{
    <span class="hljs-keyword">if</span> (!is_callable($callback)) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> \InvalidArgumentException(<span class="hljs-string">"第二个参数有误"</span>);
    }
    <span class="hljs-keyword">$this</span>-&gt;methods[$name] = \Closure::bind($callback, <span class="hljs-keyword">$this</span>, get_class());
}

<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__call</span><span class="hljs-params">(string $name, array $arguments)</span>
</span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>(<span class="hljs-keyword">$this</span>-&gt;methods[$name])) {
        <span class="hljs-keyword">return</span> call_user_func_array(<span class="hljs-keyword">$this</span>-&gt;methods[$name], $arguments);
    }

    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> \RuntimeException(<span class="hljs-string">"不存在方法[{$name}]"</span>);
}

}

// 测试
public function testClosureBind()
{
$obj = new ClosureBind();
$obj->addMethod(‘add’, function (array $params) {
return ++$params[0];
});
$this->assertEquals(2, $obj->add([1]));

<span class="hljs-comment">// 测试同一个实例</span>
$obj-&gt;addMethod(<span class="hljs-string">'test'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(array $params)</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>;
});
<span class="hljs-keyword">$this</span>-&gt;assertTrue($obj-&gt;test([<span class="hljs-number">1</span>]) <span class="hljs-keyword">instanceof</span> $obj);

}

复制代码

六、参考资料

  • php

    PHP(PHP:Hypertext Preprocessor)是一种在电脑上执行的脚本语言,主要是用途在于处理动态网页,也包含了命令列执行接口(command line interface),或者产生图形使用…

    21 引用
感谢    赞同    分享    收藏    关注    反对    举报    ...