本文主要和大家分享php中closure类详解,php closure 类是用于代表匿名函数的类,匿名函数(在 php 5.3 中被引入)会产生这个类型的对象,closure类摘要如下:
closure {
__construct ( void )
public static closure bind (closure $closure , object $newthis [, mixed $newscope = 'static' ])
public closure bindto (object $newthis [, mixed $newscope = 'static' ])
}
方法说明:
closure::__construct — 用于禁止实例化的构造函数
closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。
closure::bindto — 复制当前闭包对象,绑定指定的$this对象和类作用域。
除了此处列出的方法,还有一个 __invoke 方法。这是为了与其他实现了 __invoke()魔术方法 的对象保持一致性,但调用闭包对象的过程与它无关。
下面将介绍closure::bind和closure::bindto。
closure::bind是closure::bindto的静态版本,其说明如下:
public static closure bind (closure $closure , object $newthis [, mixed $newscope = 'static' ])
closure表示需要绑定的闭包对象。
newthis表示需要绑定到闭包对象的对象,或者null创建未绑定的闭包。
newscope表示想要绑定给闭包的类作用域,可以传入类名或类的示例,默认值是 'static', 表示不改变。
该方法成功时返回一个新的 closure 对象,失败时返回false。
例子说明:
<?php
/**
* 复制一个闭包,绑定指定的$this对象和类作用域。
*
* @author 疯狂老司机
*/
class animal {
private static $cat = "cat";
private $dog = "dog";
public $pig = "pig";
}
/*
* 获取animal类静态私有成员属性
*/
$cat = static function() {
return animal::$cat;
};
/*
* 获取animal实例私有成员属性
*/
$dog = function() {
return $this->dog;
};
/*
* 获取animal实例公有成员属性
*/
$pig = function() {
return $this->pig;
};
$bindcat = closure::bind($cat, null, new animal());// 给闭包绑定了animal实例的作用域,但未给闭包绑定$this对象
$binddog = closure::bind($dog, new animal(), 'animal');// 给闭包绑定了animal类的作用域,同时将animal实例对象作为$this对象绑定给闭包
$bindpig = closure::bind($pig, new animal());// 将animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域
echo $bindcat(),'<br>';// 根据绑定规则,允许闭包通过作用域限定操作符获取animal类静态私有成员属性
echo $binddog(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象(animal实例对象)获取animal实例私有成员属性
echo $bindpig(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象获取animal实例公有成员属性
?>
输出:
cat
dog
pig
closure::bindto — 复制当前闭包对象,绑定指定的$this对象和类作用域,其说明如下:
public closure closure::bindto (object $newthis [, mixed $newscope = 'static' ])
newthis表示绑定给闭包对象的一个对象,或者null来取消绑定。
newscope表示关联到闭包对象的类作用域,可以传入类名或类的示例,默认值是 'static', 表示不改变。
该方法创建并返回一个闭包对象,它与当前对象绑定了同样变量,但可以绑定不同的对象,也可以绑定新的类作用域。绑定的对象决定了返回的闭包对象中的$this的取值,类作用域决定返回的闭包对象能够调用哪些方法,也就是说,此时$this可以调用的方法,与newscope类作用域相同。
例子1:
<?php
function __autoload($class) {
require_once "$class.php";
}
$template = new template;
$template->render(new article, 'tpl.php');
?>
template.php 模板类
<?php
/**
* 模板类,用于渲染输出
*
* @author 疯狂老司机
*/
class template{
/**
* 渲染方法
*
* @access public
* @param obj 信息类
* @param string 模板文件名
*/
public function render($context, $tpl){
$closure = function($tpl){
ob_start();
include $tpl;
return ob_end_flush();
};
$closure = $closure->bindto($context, $context);
$closure($tpl);
}
}
article.php 信息类
<?php
/**
* 文章信息类
*
* @author 疯狂老司机
*/
class article{
private $title = "这是文章标题";
private $content = "这是文章内容";
}
tpl.php 模板文件
<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<h1><?php echo $this->title;?></h1>
<p><?php echo $this->content;?></p>
</body>
</html>
运行时确保以上文件位于同级目录。
输出:
这是文章标题这是文章内容
例子2:
<?php
/**
* 给类动态添加新方法
*
* @author 疯狂老司机
*/
trait dynamictrait {
/**
* 自动调用类中存在的方法
*/
public function __call($name, $args) {
if(is_callable($this->$name)){
return call_user_func($this->$name, $args);
}else{
throw new \runtimeexception("method {$name} does not exist");
}
}
/**
* 添加方法
*/
public function __set($name, $value) {
$this->$name = is_callable($value)?
$value->bindto($this, $this):
$value;
}
}
/**
* 只带属性不带方法动物类
*
* @author 疯狂老司机
*/
class animal {
use dynamictrait;
private $dog = 'dog';
}
$animal = new animal;
// 往动物类实例中添加一个方法获取实例的私有属性$dog
$animal->getdog = function() {
return $this->dog;
};
echo $animal->getdog();
?>
输出:
dog
例子3:
<?php
/**
* 一个基本的购物车,包括一些已经添加的商品和每种商品的数量
*
* @author 疯狂老司机
*/
class cart {
// 定义商品价格
const price_butter = 1.00;
const price_milk = 3.33;
const price_eggs = 8.88;
protected $products = array();
/**
* 添加商品和数量
*
* @access public
* @param string 商品名称
* @param string 商品数量
*/
public function add($item, $quantity) {
$this->products[$item] = $quantity;
}
/**
* 获取单项商品数量
*
* @access public
* @param string 商品名称
*/
public function getquantity($item) {
return isset($this->products[$item]) ? $this->products[$item] : false;
}
/**
* 获取总价
*
* @access public
* @param string 税率
*/
public function gettotal($tax) {
$total = 0.00;
$callback = function ($quantity, $item) use ($tax, &$total) {
$priceperitem = constant(__class__ . "::price_" . strtoupper($item));
$total += ($priceperitem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);;
}
}
$my_cart = new cart;
// 往购物车里添加商品及对应数量
$my_cart->add('butter', 10);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 12);
// 打出出总价格,其中有 5% 的销售税.
echo $my_cart->gettotal(0.05);
?>
输出:
132.88
补充说明:闭包可以使用use关键连接外部变量。
总结:合理使用闭包能使代码更加简洁和精炼。
相关推荐:
介绍php中closure使用实例
php 中的closure用法实例详解
php 中closure的介绍
以上就是php中closure类详解的详细内容。