本文主要和大家分享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中文網其他相關文章!