php两层匿名函数,php (匿名函数和闭包)

一、什么是闭包

1、闭包和匿名函数在php5.3.0中两个php新特性,使用的也最多,这两个特性听起来很吓人, 其实很容易理解,这两个特性非常有用,每个php开发者都应该掌握。

2、闭包是指在创建时封装周围状态的函数,即便闭包所在的环境不存在了,闭包中封装的状态依然存在,这个概念很难理解 不过一单掌握了,将会对你的生活带来巨大的变化。

3、匿名函数其实就是没有名称的函数,匿名函数可以赋值给变量,还能像其他任何php对象那样传递,不过匿名函数仍然是 匿名函数,因此可以调用,还可以传入参数,匿名函数特别适合作为函数或方法的回调。 理论上讲,闭包和匿名函数是不同的概念,不过,php将其视作相同的概念,所以,我提到闭包时,指的也是匿名函数, 反之亦然。

4、php闭包和匿名函数使用的句法和普通函数相同,不过别被这一点迷惑了,闭包和匿名函数其实是伪装成函数的对象, 如果审查php闭包和匿名函数,会发现他们是Closure类的实例,闭包和字符串或整数一样,也是一等值类型。

二、创建一个闭包

$closure = function ($name) {

return sprintf('Hello %s', $name);

};

echo $closure('Yee Jason');

输出 Hello Yee Jason.

之所以能调用$closure变量,是因为这个变量的值是一个闭包,而且闭包对象实现了 __invoke()魔术方法,只要

变量名后面有 (),php就会查并调用__invoke() 方法。

我通常把闭包当做函数和方法的回调使用,很多php函数都会用到回调函数,例如 array_map和preg_replace_callback() 是使用匿名函数的绝佳时机,记住,闭包和其他值一样,可以作为参数传入其他php函数。

$numberPlusOne = array_map(function($number) {

return $number + 1;

}, [1, 2, 3]);

print_r($numberPlusOne);

在PHP闭包之前, php开发者无法选择,只能单独创建具名函数,然后引用那个函数,这么做,代码执行的稍微慢一点, 而且把回调的实现和使用场所隔离开了,传统的php代码:

function incrementNumber($number)

{

return $number + 1;

}

$numberPlusOne = array_map('incrementNumber', [1, 2, 3]);

print_r($numberPlusOne);

以上两个例子输出:Array ( [0] => 2 [1] => 3 [2] => 4 )

三、附加状态

前面演示了如何把匿名函数当成回调使用,下面探讨如何为php闭包附加并封装状态,javascript开发者

可能对php的闭包感到奇怪,因为php闭包不会像真正的javascript闭包那样自动封装应用的状态,在php中,

必须手动调用闭包对象的bindTo()方法或者使用use 关键字,把状态附加到php闭包上。

使用 use 关键字附加闭包状态常见的多,因此我们先看这种方式,使用use 关键字把变量附加到闭包上时,

附加的变量会记住附件时付给他的值。

function enclosePerson($name)

{

return function ($doCommand) use ($name) {

return sprintf('%s, %s', $name, $doCommand);

};

}

$clay = enclosePerson('Clay');

echo $clay('get me sweet tea!');

以上代码输出:Clay get me sweet tea

使用use关键字,把多个参数传入闭包时,需要还是用,号分隔开。

具名函数enclosePerson() 有个名为$name的参数,这个函数返回一个闭包对象,而且这个闭包对象封装了 $name参数,  即便 返回的闭包对象跳出了 enclosePerson() 函数的作用域,它也会记住$name参数的值,因为$name变量仍在闭包中。

使用bindTo方法附加闭包的状态

别忘了php 闭包是对象,与任何其他的php对象类似,每个闭包实例都可以使用$this关键字获取闭包的内部状态。

闭包对象的默认状态没什么用,不过有一个 __invoke()魔术方法和bindTo() 方法,仅此而已。

但是bindTo() 方法为闭包增加了一些有趣的潜力,我们可以使用这个方法把Closure对象的内部状态绑定到其他的对象上,

bindTo() 方法的第二个参数很重要,其作用是指定绑定闭包的那个对象所属的php类,因此闭包可以访问绑定闭包的对象中

受保护和私有的成员变量。

你会发现,php框架经常使用bindTo()方法把路由URL映射到匿名回调函数上,框架会把匿名函数绑定到应用对象上,

这么做可以在这个匿名函数中使用 $this关键字引用重要的对象。

例子:

class APP

{

protected $routes = array();

protected $responseStatus = '200 ok';

protected $responseContentType = 'text/html';

protected $responseBody = 'hello world';

public function addRoute($routePath, $routeCallback)

{

$this->routes[$routePath] = $routeCallback->bindTo($this, __CLASS__);

}

public function dispath($currentPath)

{

foreach ($this->routes as $routePath => $callback) {

if ($routePath == $currentPath) {

$callback();

}

}

header('HTTP/1.1'. $this->responseStatus);

header('Content-type' . $this->responseContentType);

header('Content-length' . $this->responseBody);

echo $this->responseBody;

}

}

我们要特别注意addRoute方法,这个方法的参数分别是一个路由路径和路由回调,dispatch() 方法的参数是当前的HTTP请 求的  路径,它会调用匹配的路由回调,我们把路由绑定到当前的App实例上,这么做就能再回调函数中处理App实例的状态 。

$app = new App();

$app->addRoute('/users/josh', function () {

$this->responseContentType = 'application/json; charset=utf8';

$this->responseBody = '{"name" : "yee Jason"}';

});

$app->dispatch('/users/josh');

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值