Maison  >  Article  >  développement back-end  >  Explication détaillée de la classe Closure en PHP

Explication détaillée de la classe Closure en PHP

小云云
小云云original
2018-03-22 09:48:462569parcourir

Cet article partage principalement avec vous une explication détaillée de la classe Closure en PHP. La classe PHP Closure est une classe utilisée pour représenter des fonctions anonymes (introduites dans PHP 5.3) qui généreront des objets de ce type. la classe Closure est la suivante :

Closure {
    __construct ( void )
    public static Closure bind (Closure $closure , object $newthis [, mixed $newscope = 'static' ])
    public Closure bindTo (object $newthis [, mixed $newscope = 'static' ])
}

Description de la méthode :

Closure::__construct — Constructeur utilisé pour interdire l'instanciation
Closure::bind — Copier une fermeture, lier le spécifié $ cet objet et la portée de la classe.
Closure::bindTo — Copiez l'objet de fermeture actuel et liez l'objet $this et la portée de classe spécifiés.

En plus des méthodes répertoriées ici, il existe également une méthode __invoke. Ceci est par souci de cohérence avec d'autres objets qui implémentent la méthode magique __invoke(), mais le processus d'invocation de l'objet de fermeture n'a rien à voir avec cela.

Ce qui suit présentera Closure::bind et Closure::bindTo.

Closure::bind est la version statique de Closure::bindTo, et sa description est la suivante :

public static Closure bind (Closure $closure , object $newthis [, mixed $newscope = 'static' ])

closure représente l'objet de fermeture qui doit être lié.
newthis représente l'objet qui doit être lié à l'objet de fermeture, ou NULL pour créer une fermeture indépendante.
newscope représente la portée de la classe que vous souhaitez lier à la fermeture. Vous pouvez transmettre le nom de la classe ou l'exemple de classe. La valeur par défaut est « statique », ce qui signifie aucun changement.

Cette méthode renvoie un nouvel objet Closure en cas de succès et FALSE en cas d'échec.

Exemple :

<?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实例公有成员属性
?>

Sortie :

chat
chien
cochon

Closure::bindTo — Copiez l'objet de fermeture actuel et liez l'objet $this et la portée de classe spécifiés. La description est la suivante :

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

newthis représente un objet lié à l'objet de fermeture, ou NULL pour annuler la liaison. .
newscope représente la portée de classe associée à l'objet de fermeture. Vous pouvez transmettre le nom de la classe ou l'exemple de classe. La valeur par défaut est « statique », ce qui signifie aucun changement.

Cette méthode crée et renvoie un objet de fermeture, qui lie les mêmes variables que l'objet actuel, mais peut lier différents objets ou une nouvelle portée de classe. L'objet lié détermine la valeur de $this dans l'objet de fermeture renvoyé et la portée de la classe détermine les méthodes que l'objet de fermeture renvoyé peut appeler. En d'autres termes, les méthodes que $this peut appeler à ce moment-là fonctionnent avec la classe newscope. le domaine est le même.

Exemple 1 :

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

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

Classe de modèle 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);
    }

}

Classe d'informations Article.php

<?php
/** 
 * 文章信息类 
 * 
 * @author 疯狂老司机 
 */
class Article{
    private $title = "这是文章标题";
    private $content = "这是文章内容";
}

tpl Lors de l'exécution du fichier modèle .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>

, assurez-vous que les fichiers ci-dessus se trouvent dans le même répertoire.

Sortie :

Voici le titre de l'article

Voici le contenu de l'article

Exemple 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();

?>

Sortie :

chien

Exemple 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);

?>

Sortie :

132.88

Remarque supplémentaire : les fermetures peuvent utiliser la touche USE pour connecter des variables externes.

Résumé : Une utilisation appropriée des fermetures peut rendre le code plus concis et raffiné.
Recommandations associées :

Introduction aux exemples d'utilisation de fermeture en php

Explication détaillée des exemples d'utilisation de fermeture en php

Introduction à la fermeture en php

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn