PHP中Closure類詳解

來源:互聯網
上載者:User
本文主要和大家分享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::bindClosure::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:

<?phpfunction __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的介紹

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.