How PHP creates anonymous functions based on the Closure class
This example describes how to create an anonymous function based on the Closure class in PHP. We will share this with you for your reference. The details are as follows:
Closure class
Class used to represent anonymous functions.
Anonymous functions (introduced in PHP 5.3) generate objects of this type. In the past, this class was regarded as an implementation detail, but now we can rely on it to do something. Since PHP 5.4, this class has some methods that allow more control over anonymous functions after they are created.
This class cannot be instantiated. There are two main methods used to copy the closure, one static and one dynamic. The two methods that are hard to understand are described in detail below.
Closure: bind
public static Closure Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
Parameter description:
Closure
The anonymous function to be bound.
Newthis
The object to be bound to an anonymous function, or NULL creates an unbound closure.
Newscope
The class scope that you want to bind to the closure, or 'static 'indicates that it will not change. If an object is input, the type name of the object is used. The class scope is used to determine the visibility of the $ this object in the closure and the protection method.
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.
The above is the definition of this method. The first parameter is a closure function, and the second parameter is not easy to understand. If the closure to be copied contains $ this, this object indicates this $ this. The changes to this object in the closure function will be consistent after the call, for example, modifying an attribute. The third parameter is not easy to understand, according to the official instructions, it is also in the cloud. By default, when you call $ this-> to access the attribute functions in object $ newthis, there are limits. You can only access functions with the public attribute, if you want to access the protected/private attribute, you need to set it to the corresponding class name/class instance, you need to access the protection/private attribute function of that class just like in the class.
Example
<? Phpclass T {private function show () {echo "I am a private function in T: show \ n";} protected function who () {echo "I'm the protection function in T: who \ n";} public function name () {echo "I'm the public function in T: name \ n ";}} $ test = new T (); $ func = Closure: bind (function () {$ this-> who (); $ this-> name (); $ this-> show () ;}, $ test); $ func ();
The above code will report the error Fatal Error: Uncaught error: Call to protected method T: who () from context 'Closure '.
When the third bind parameter is t: class or new T (), every result is output normally.
I am the protection function in T: who, I am the public function in T: name, I am the private function in T: show
Of course, the closure can also pass parameters.
$ Test = new StdClass (); var_dump ($ test); $ func = Closure: bind (function ($ obj) {$ obj-> name = "Yan ruitao" ;}, null); $ func ($ test); var_dump ($ test );
Similar to anonymous functions, the above program does not depend on any object. The above program will output:
Object (stdClass) #1 (0) {} object (stdClass) #1 (1) {["name"] => string (9) "Yan ruitao "}
There is also a special example to explain
<? Phpclass T {private function show () {echo "I am a private function in T: show \ n";} protected function who () {echo "I'm the protection function in T: who \ n";} public function name () {echo "I'm the public function in T: name \ n ";}} $ func = Closure: bind (function ($ obj) {$ obj-> show () ;}, null); $ test = new T (); $ func ($ test );
What will be output in the above situation? Yes, an error will be reported, prompting that the private property show cannot be accessed. At this time, you can add the third parameter, the third parameter affects not only the $ this scope, but also the scope of the parameter.
Closure: bindTo
The bindTo and bind functions are similar. Here, only another form is used to copy the current closure object and bind the specified $ this object and Class scope ., The first parameter is less than bind, and the last two are the same. Of course, the difference is that bindTo is not a static method, but a property method that exists only when it is a closure.
Example
<? Phpclass T {private function show () {echo "I am a private function in T: show \ n";} protected function who () {echo "I'm the protection function in T: who \ n";} public function name () {echo "I'm the public function in T: name \ n ";}} $ func = function () {$ this-> show (); $ this-> who (); $ this-> name ();}; $ funcNew = $ func-> bindTo (new T (), T: class); $ funcNew ();
The output of the above function is similar to that of the bind
I am a private function in T: show I am a protection function in T: who I am a public function in T: name
One trick
This function is encountered when you look at the automatically loaded source code generated by composer. It is particularly used in composer. The following is a part of the code in composer.
// File catalog (\ Composer \ Autoload \ catalog: getInitializer ($ loader); // file autoload_static.phppublic static function getInitializer (ClassLoader $ loader) {return \ Closure :: bind (function () use ($ loader) {$ loader-> prefixLengthsPsr4 = Response: $ prefixLengthsPsr4; $ loader-> prefixDirsPsr4 = Response: $ prefixDirsPsr4; $ loader-> prefixesPsr0 = secure: $ prefixesPsr0; $ loader-> classMap = secure: $ classMap;}, null, ClassLoader: class );}
The code above is quite strange. In call_user_func, the first thought is to pass the error parameter. In fact, it is not. A function is called here. This function will return a Closure object, which is an anonymous function, the final input parameter is still a callable type. Let's look at the returned closure, which uses use, which is a bridge connecting the closure and external variables.
The common parameter passing is acceptable because in php5, object parameters and real parameters point to the same object, and modifications to objects in the function are reflected outside the object.
Therefore, it is okay to do this. There is another form.
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);}