Maison  >  Article  >  développement back-end  >  Introduction à l'utilisation de Closure pour créer des fonctions anonymes en PHP

Introduction à l'utilisation de Closure pour créer des fonctions anonymes en PHP

青灯夜游
青灯夜游avant
2020-07-28 17:49:231815parcourir

Introduction à l'utilisation de Closure pour créer des fonctions anonymes en PHP

Classe de fermeture

Une classe utilisée pour représenter des fonctions anonymes.

Les fonctions anonymes (introduites dans PHP 5.3) produisent des objets de ce type. Dans le passé, cette classe était considérée comme un détail d'implémentation, mais on peut désormais compter sur elle pour faire quelque chose. Depuis PHP 5.4, cette classe est livrée avec des méthodes qui permettent plus de contrôle sur la fonction anonyme après sa création.

Cette classe ne peut pas être instanciée. Elle contient deux méthodes principales, toutes deux utilisées pour copier des fermetures, une statique et une dynamique. Ces deux méthodes difficiles à comprendre sont expliquées en détail. ci-dessous.

Closure::bind

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

参数说明:
closure
需要绑定的匿名函数。

newthis
需要绑定到匿名函数的对象,或者 NULL 创建未绑定的闭包。

newscope
想要绑定给闭包的类作用域,或者 'static' 表示不改变。如果传入一个对象,则使用这个对象的类型名。 类作用域用来决定在闭包中 $this 对象的 
私有、保护方法 的可见性。 The class scope to which associate the closure is to be associated, or 'static' to keep the 
current one. If an object is given, the type of the object will be used instead. This determines the visibility of 
protected and private methods of the bound object.

Description du paramètre :

  • la fermeture doit être liée de manière anonyme fonction.

  • newthis nécessite un objet lié à une fonction anonyme, ou NULL pour créer une fermeture indépendante.

  • newscope veut être lié à la portée de classe de la fermeture, ou « statique » signifie inchangé. Si un objet est transmis, le nom de type de l'objet est utilisé. La portée de la classe est utilisée pour déterminer la visibilité des méthodes privées et protégées de l'objet $this dans la fermeture.

La portée de classe à laquelle associer la fermeture doit être associée, ou 'statique' pour conserver celle

actuelle si un objet est donné, le type de l'objet sera utilisé à la place. Cela détermine la visibilité des

méthodes protégées et privées de l'objet lié.

Ce qui précède est la définition de la méthode,

Le premier paramètre est facile à comprendre, c'est une fonction de fermeture

Le deuxième paramètre n'est pas facile à comprendre Si la fermeture à copier contient $this, cet objet représente ceci, les modifications apportées à cet objet dans la fonction de fermeture resteront cohérentes une fois l'appel terminé, comme la modification d'un attribut $this

Le troisième paramètre n'est pas facile à comprendre, et la description officielle indique également que Dans le brouillard, sous les paramètres par défaut, lors de l'appel de

pour accéder à la fonction d'attribut dans $this->, il y aura des restrictions. Vous ne pouvez accéder à la fonction de l'attribut object $newthis que si vous souhaitez accéder à l'attribut public. , vous devez définir Pour le nom de classe/l'instance de classe correspondant, vous devez accéder aux fonctions d'attribut protégé/privé de cette classe comme dans la classe. protected/private

Exemple

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$test = new T();

$func = Closure::bind(function(){
    $this->who();
    $this->name();
    $this->show();
}, $test);

$func();

Le code ci-dessus signalera une erreur

. L'ajout du troisième paramètre de bind à Fatal error: Uncaught Error: Call to protected method T::who() from  context 'Closure' ou t::class affichera chaque résultat normalement. new T()

我是T里面的保护函数:who
我是T里面的公共函数:name
我是T里面的私有函数:show

Bien sûr, les fermetures peuvent également transmettre des paramètres

$test = new StdClass();
var_dump($test);

$func = Closure::bind(function($obj){
    $obj->name = "燕睿涛";
}, null);

$func($test);
var_dump($test);

Le programme ci-dessus est le même que la fonction anonyme et n'a aucune dépendance sur aucun objet. Le programme ci-dessus affichera :

object(stdClass)#1 (0) {
}
object(stdClass)#1 (1) {
  ["name"]=>
  string(9) "燕睿涛"
}
.

Il y a aussi un exemple spécial qui doit être expliqué

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$func = Closure::bind(function ($obj) {
    $obj->show();
}, null);

$test = new T();

$func($test);

Que sera le résultat dans la situation ci-dessus ? Oui, une erreur sera signalée, indiquant que l'attribut privé n'est pas accessible

. Pour le moment, ajoutez simplement le troisième paramètre. Oui, j'ai vu que le troisième paramètre affecte non seulement la portée de show, mais $this peut également affecter la portée des paramètres.

Closure::bindTo

et bindTo ont des fonctions similaires, voici juste une autre forme, les deux sont bind , le premier paramètre est inférieur à 复制当前闭包对象,绑定指定的$this对象和类作用域。, et les deux derniers de bind sont identiques. Bien sûr, une autre différence est que
n'est pas une méthode statique, mais une méthode attributaire qui n'existe que dans les fermetures. bindTo

Exemple

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$func = function () {
    $this->show();
    $this->who();
    $this->name();
};

$funcNew = $func->bindTo(new T(), T::class);

$funcNew();

La sortie de la fonction ci-dessus est similaire à celle de

bind

我是T里面的私有函数:show
我是T里面的保护函数:who
我是T里面的公共函数:name

Une astuce

Cette fonction a été rencontrée en regardant le code source de chargement automatique généré par composer. Elle est utilisée spécialement dans composer. Ce qui suit est une interception d'une partie du code dans composer

.

// 文件autoload_real.php
call_user_func(\Composer\Autoload\ComposerStaticInit898ad46cb49e20577400c63254121bac::getInitializer($loader));

// 文件autoload_static.php
public static function getInitializer(ClassLoader $loader)
{
    return \Closure::bind(function () use ($loader) {
        $loader->prefixLengthsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixLengthsPsr4;
        $loader->prefixDirsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixDirsPsr4;
        $loader->prefixesPsr0 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixesPsr0;
        $loader->classMap = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$classMap;

    }, null, ClassLoader::class);
}

Le code ci-dessus C'est assez étrange. Dans

, la première impression est que de mauvais paramètres sont passés. En fait, ce n'est pas le cas. Cette fonction renverra un call_user_func. object. Closure est également une fonction anonyme. Le paramètre final passé est toujours un type
. Regardez à nouveau la fermeture renvoyée callable qui est utilisée, qui est le pont reliant la fermeture et les variables externes. useQuant à la raison pour laquelle des paramètres ordinaires peuvent être transmis ici, c'est parce qu'en PHP5, les paramètres formels de l'objet et les paramètres réels pointent vers le même objet, et les modifications apportées à l'objet dans la fonction seront reflétées à l'extérieur de l'objet.

Donc, c'est bien de faire ce qui précède, il existe aussi un autre formulaire

call_user_func(\Composer\Autoload\ComposerStaticInit898ad46cb49e20577400c63254121bac::getInitializer(), $loader);

public static function getInitializer()
{
    return \Closure::bind(function ($loader) {
        $loader->prefixLengthsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixLengthsPsr4;
        $loader->prefixDirsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixDirsPsr4;
        $loader->prefixesPsr0 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixesPsr0;
        $loader->classMap = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$classMap;

    }, null, ClassLoader::class);
}

Résumé

Je ne l'ai pas fait je blogue depuis longtemps. Parfois, je suis trop irritable et je n'arrive pas à me calmer. Parfois, je ne trouve tout simplement pas ce que je veux écrire. Il faut quand même se calmer, tout bien faire, ne pas s'agiter quand les choses arrivent, garder l'esprit ouvert et gérer tout sereinement.

Tutoriels associés recommandés : "Tutoriel 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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer