Maison  >  Article  >  développement back-end  >  Introduction à la fermeture en php

Introduction à la fermeture en php

零下一度
零下一度original
2017-06-23 14:24:401123parcourir

Les fonctions de fermeture, anonymes, ont été introduites dans php5.3, également connues sous le nom de fonctions anonymes. Le sens littéral est une fonction sans nom défini. Par exemple, le code suivant (le nom du fichier est do.php)

<?phpfunction A() {return 100;
};function B(Closure $callback)
{return $callback();
}$a = B(A());print_r($a);//输出:Fatal error: Uncaught TypeError: Argument 1 passed to B() must be an instance of Closure, integer given, called in D:\web\test\do.php on line 11 and defined in D:\web\test\do.php:6 Stack trace: #0 D:\web\test\do.php(11): B(100) #1 {main} thrown in D:\web\test\do.php on line 6?>

A() ici ne peut jamais être utilisé comme paramètre de B, car A n'est pas un " fonction "anonyme".

Il devrait donc être modifié comme suit :

<?php$f = function () {return 100;
};function B(Closure $callback)
{return $callback();
}$a = B($f);print_r($a);//输出100
<?$func = function( $param ) {echo $param;
};$func( &#39;hello word&#39; );//输出:hello word

Implémenter la fermeture

Mettre la fonction anonyme dans ordinaire Il est transmis en paramètre dans la fonction et peut également être renvoyé. Cela implémente une fermeture simple.

Je vais vous donner trois exemples ci-dessous :

<?php//例一
//在函数里定义一个匿名函数,并且调用它function printStr() {$func = function( $str ) {echo $str;
    };$func( &#39; hello my girlfriend ! &#39; );
}
printStr();//输出 hello my girlfriend !

//例二
//在函数中把匿名函数返回,并且调用它function getPrintStrFunc() {$func = function( $str ) {echo $str;
    };return $func;
}$printStrFunc = getPrintStrFunc();$printStrFunc( &#39; do you  love me ? &#39; );//输出 do you  love me ?

//例三
//把匿名函数当做参数传递,并且调用它function callFunc( $func ) {$func( &#39; no!i hate you &#39; );
}$printStrFunc = function( $str ) {echo $str.&#39;<br>';
};
callFunc( $printStrFunc );//也可以直接将匿名函数进行传递。如果你了解js,这种写法可能会很熟悉callFunc( function( $str ) {echo $str; //输出no!i hate you
} );

Mots clés qui relient les fermetures et les variables externes : UTILISER

Les fermetures peuvent enregistrer l'emplacement Certaines variables et valeurs du contexte du bloc de code. Par défaut en PHP, les fonctions anonymes ne peuvent pas appeler de variables de contexte dans le bloc de code où elles se trouvent, mais doivent utiliser le mot-clé use.

Prenons un autre exemple (enfin, je suis à court d'argent, je suis vulgaire) :

<?phpfunction getMoney() {$rmb = 1;$dollar = 8;$func = function() use ( $rmb ) {echo $rmb;echo $dollar;
    };$func();
}
getMoney();//输出:1

Comme vous pouvez le constater, le dollar n'est pas dedans l'instruction use password, elle ne peut pas être obtenue dans cette fonction anonyme, alors faites attention à ce problème pendant le développement.

Certaines personnes peuvent se demander si les variables de contexte peuvent être modifiées dans les fonctions anonymes, mais j'ai trouvé que cela ne semble pas possible :

<?phpfunction getMoney() {$rmb = 1;$func = function() use ( $rmb ) {echo $rmb.&#39;<br>';//把$rmb的值加1$rmb++;
    };$func();echo $rmb;
}

getMoney();//输出:
//1
//1

Eh bien, il s'avère que l'utilisation Ce qui est référencé n'est qu'un clone de la variable. Mais que faire si je veux citer complètement la variable au lieu de la copier ? Pour obtenir cet effet, ajoutez simplement un symbole & avant la variable :

<?phpfunction getMoney() {$rmb = 1;$func = function() use ( &$rmb ) {echo $rmb.&#39;<br>';//把$rmb的值加1$rmb++;
    };$func();echo $rmb;
}

getMoney();//输出:
//1
//2

D'accord, donc anonyme La fonction peut alors référencer les variables de contexte. Si la fonction anonyme est renvoyée au monde extérieur, la fonction anonyme enregistrera les variables référencées par l'utilisation, mais le monde extérieur ne pourra pas obtenir ces variables. De cette façon, le concept de « fermeture » peut être plus clair.

Selon la description, changeons l'exemple ci-dessus :

<?phpfunction getMoneyFunc() {$rmb = 1;$func = function() use ( &$rmb ) {echo $rmb.&#39;<br>';//把$rmb的值加1$rmb++;
    };return $func;
}$getMoney = getMoneyFunc();$getMoney();$getMoney();$getMoney();//输出:
//1
//2
//3

D'accord, tant pis, alors si nous voulons appeler une fonction anonyme dans une classe Woolen tissu? Accédez directement à la démo

<?phpclass A {public static function testA() {return function($i) { //返回匿名函数return $i+100;
        };
    }
}function B(Closure $callback)
{return $callback(200);
}$a = B(A::testA());print_r($a);//输出 300

où A::testA() renvoie une fonction sans nom.

Le concept de liaison

La fermeture dans l'exemple ci-dessus n'est qu'une fonction anonyme globale. D'accord, nous voulons maintenant spécifier une classe pour avoir une fonction anonyme. On comprend également que la portée d'accès de cette fonction anonyme n'est plus globale, mais la portée d'accès d'une classe.

Ensuite, nous devons lier "une fonction anonyme à une classe".

<?phpclass A {public $base = 100;
}class B {private $base = 1000;
}$f = function () {return $this->base + 3;
};$a = Closure::bind($f, new A);print_r($a());//输出 103echo PHP_EOL;$b = Closure::bind($f, new B , 'B');print_r($b());//输出1003

Dans l'exemple ci-dessus, fCecipersonneanonymenomlettrenuméromonomimpairmerveilleux deAprès la liaison, c'est comme s'il existait une telle fonction dans A, mais que cette fonction soit publique ou privée, le dernier paramètre de bind indique cette fonction portée appelable. Vous avez vu bindTo ci-dessus, jetons un œil à l'introduction sur le site officiel Valeur de retour : Renvoie un nouvel objet Closure ou retour sur échec

Regardons un exemple pour approfondir notre compréhension :

Regardons regardez une démo :
(PHP 5 >= 5.4.0, PHP 7)Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。

说明

public static Closure Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
这个方法是 Closure::bindTo() 的静态版本。查看它的文档获取更多信息。

参数

closure
需要绑定的匿名函数。

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

newscope
想要绑定给闭包的类作用域,或者 'static' 表示不改变。如果传入一个对象,则使用这个对象的类型名。 类作用域用来决定在闭包中 $this 对象的 私有、保护方法 的可见性。(备注:可以传入类名或类的实例,默认值是 'static', 表示不改变。)


FALSEGrâce aux exemples ci-dessus, il n'est en fait pas difficile de comprendre la liaison anonyme.... Nous examinons une démo étendue (introduisant des fonctionnalités de trait)

<?phpclass A {private static $sfoo = 1;private $ifoo = 2;
}$cl1 = static function() {return A::$sfoo;
};$cl2 = function() {return $this->ifoo;
};$bcl1 = Closure::bind($cl1, null, 'A');$bcl2 = Closure::bind($cl2, new A(), 'A');echo $bcl1(), "\n";//输出 1echo $bcl2(), "\n";//输出 2
Par exemple, nous utilisons désormais l'environnement commercial actuel

<?phpclass A {public $base = 100;
}class B {private $base = 1000;
}class C {private static $base = 10000;
}$f = function () {return $this->base + 3;
};$sf = static function() {return self::$base + 3;
};$a = Closure::bind($f, new A);print_r($a());//这里输出103,绑定到A类echo PHP_EOL;$b = Closure::bind($f, new B , 'B');print_r($b());//这里输出1003,绑定到B类echo PHP_EOL;$c = $sf->bindTo(null, 'C'); //注意这里:使用变量#sf绑定到C类,默认第一个参数为nullprint_r($c());//这里输出10003

Remarque supplémentaire : les fermetures peuvent utiliser la touche USE pour connecter des variables externes.
Résumé : Les caractéristiques des fermetures PHP peuvent en fait permettre d'obtenir des fonctions similaires, voire plus puissantes, en utilisant CLASS, sans parler des fermetures de js. Nous ne pouvons qu'attendre avec impatience des améliorations dans la prise en charge des fermetures PHP à l'avenir. Cependant, les fonctions anonymes restent très utiles. Par exemple, lorsque vous utilisez des fonctions telles que preg_replace_callback, vous n'avez pas besoin de déclarer une fonction de rappel en externe. Une utilisation appropriée des fermetures peut rendre le code plus concis et raffiné.

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