首頁  >  文章  >  後端開發  >  PHP中Closure類詳解

PHP中Closure類詳解

小云云
小云云原創
2018-03-22 09:48:462631瀏覽

本文主要和大家分享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(), &#39;Animal&#39;);// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包
$bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域
echo $bindCat(),&#39;<br>&#39;;// 根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性
echo $bindDog(),&#39;<br>&#39;;// 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性
echo $bindPig(),&#39;<br>&#39;;// 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性
?>

輸出:

cat
dog
pig

Closure::bindTo —複製目前閉包對象,綁定指定的$this對象和類別作用域,其說明如下:

public Closure Closure::bindTo (object $newthis [, mixed $newscope = &#39;static&#39; ])

#newthis表示綁定給閉包對象的一個對象,或者NULL來取消綁定。
newscope表示關聯到閉包物件的類別作用域,可以傳入類別名稱或類別的範例,預設值是 'static', 表示不改變。

該方法創建並返回一個閉包對象,它與當前對象綁定了相同變量,但可以綁定不同的對象,也可以綁定新的類作用域。綁定的物件決定了傳回的閉包物件中的$this的取值,類別作用域決定傳回的閉包物件能夠呼叫哪些方法,也就是說,此時$this可以呼叫的方法,與newscope類別作用域相同。

範例1:

<?php
function __autoload($class) {
    require_once "$class.php";
}

$template = new Template;
$template->render(new Article, &#39;tpl.php&#39;);
?>

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 = &#39;dog&#39;;
}

$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(&#39;butter&#39;, 10);
$my_cart->add(&#39;milk&#39;, 3);
$my_cart->add(&#39;eggs&#39;, 12);

// 打出出总价格,其中有 5% 的销售税.
echo $my_cart->getTotal(0.05);

?>

輸出:

132.88

#補充說明:閉包可以使用USE關鍵連接外部變數。

總結:合理使用閉包能讓程式碼更簡潔精進。
相關推薦:

介紹php中closure使用實例

#php 中的closure用法實例詳解

php 中closure的介紹

#

以上是PHP中Closure類詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn