Closed Package
Closures and anonymous functions are starting from PHP 5.3.0, which is my favorite and most used PHP feature. Hearing these names is especially true (at least when I first heard them), but in fact it's really good to understand. They are the most useful tool necessary for each PHP Developer's toolkit.
Closures act as a function that encapsulates the external state when it is created. The state of the package is kept in the closure even though the environment when the closure was originally created does not already exist. This is a less well-mastered concept, and once you can figure it out, it feels like a new chapter in your life.
An anonymous function is actually a function without a name. An anonymous function can be assigned to a variable and passed in the code like all other PHP objects. But it's still a function, so you can call it and pass arguments. The greatest use of an anonymous function is as a callback to a function or method.
Closures and anonymous functions are theoretically different concepts. However, PHP considers them to be matter. So, when I say closures, it's also possible to refer to anonymous functions and vice versa.
PHP's closures and anonymous functions are syntactically identical to functions, but don't confuse them. They are actually objects disguised as functions. If you print a check for a PHP closure or anonymous function type, you will find that they are all instances of the closure class. Closure can be seen as a data type that is as important as string and integer.
Create
We all know that PHP's closures and functions look very much alike. You won't be surprised when you create a PHP closure like in example 2-19.
Example 2-19 simple closures
<?php$closure = function ($name) { return sprintf (' Hello%s ', $name);}; Echo $closure ("Josh");//output--"Hello Josh"
It's so simple. Example 2-19 creates a closure object and assigns it to the variable $closure. It looks like a standard PHP function: It uses the same syntax, receives parameters, and has a return value. But it doesn't have a name.
We can call the $closure variable, because $closure is a closure, closure closure objects are implemented \_invoke () this magic method. PHP automatically finds and calls the __invoke () method when the variable name follows a pair of () symbols.
I usually use the PHP closure object as a callback for functions and methods. Many PHP functions use callback functions, such as Array_map () and Preg_replace_callback (). This is like a function for the number of anonymous letters PHP! Remember, like any other value, closures can be passed to other PHP functions like parameters. In example 2-10 I use a closure object as the callback parameter of the Array_map () function.
Example 2-20 array_map closure
<?php$numbersplusone = Array_map (function ($number) { return $number +1;}, [[i]];p rint_r ($numbersPlusOne); /output--[2,3,4]
It's not that impressive, is it? But remember, PHP developers do not have a good choice to implement such a function before the closure function occurs, they can only create a named function and pass the function name as a parameter. This can be slow to execute, and most importantly it separates the implementation and use of callbacks. The old-fashioned PHP developers use the following code:
The implementation of the <?php//named callback function Incrementnumber ($number) { return $number + 1;} The use of the named callback is $numberplusone = Array_map (' Incrementnumber ', [I/n]);p rint_r ($numberPlusOne);
Although the above code can be performed normally, there is no brevity in example 2-20. We do not need a single-use function named Incrementnumber () as a callback. Using closures as callbacks can create more concise, more readable code.
Attachment State
So far we've shown how to use the nameless (also called anonymous) function as a callback. Let's look at how to use the PHP closure attachment and encapsulation state. JavaScript developers may be confused about PHP closures, because PHP's closures do not automatically encapsulate the state of the application to the closure as JavaScript does. Instead, you must manually call the Bintto () method of the closure object or use the keyword to attach the state to a PHP closure.
usually we use the Using keyword to attach the closure state, so let's take this as an example (example 2-21). When you attach a variable to a closure using the USE keyword, the value of the attached variable remains as the value of the moment the variable is attached to the closure .
Example 2-21 attaching a closure state using the USE keyword
<?phpfunction Encloseperson ($name) { return function ($doCommand) use ($name) { return sprintf ('%s,%s ', $ Name, $doCommand);} ;} Wrap the string "Clay" into the closure packet $clay = Encloseperson (' Clay ');//Call the closure echo $clay (' Get Me Sweet tea! '); /output--"Clay, Get Me Sweet tea!"
In example 2-21, the named function Encloseperson () function receives a $name parameter, returning a closure object that encapsulates the $name parameter. Even though the closure eventually leaves the scope of the Encloseperson () function, the returned closure object $clay still retains the value of the $name parameter when it is attached to the closure. Also say, $name variable still exists in the closure!
You can pass multiple parameters to the closure using the USE keyword. The parameters are separated by commas, just like the parameters of a function or method you normally use in PHP.
Don't forget that PHP closures are objects. Each instance of a closure has its internal state, and we can use the $this keyword to get those states, like other PHP objects. The default state of a closure object is rather uninteresting, it contains a magic method __invoke () and a BindTo () method, that's all.
But the BindTo () method can lead us to discover some interesting implementations. This method allows us to bind the internal state of the closure object to another object. The second parameter of the BindTo () method is quite critical, and it can specify the class of the object that the closure needs to be bound to. This allows us to get the member variables of protected and private in the bound object in the closure.
You will find that the BindTo () method is often used by some PHP frameworks to map routing addresses to anonymous callback functions. These frameworks bind an anonymous function to an Application object. You can use the $this keyword in an anonymous function to refer to the Application object, as shown in example 2-22
Example 2-22 attaching the closure state using the BindTo method
<?phpclass app{ protected $routes = Array (); protected $responseStatus = ' OK '; protected $responseContentType = ' text/html '; protected $responseBody = ' Hello world '; Public Function Addroute ($routePath, $routeCallback) { $this->routes[$routePath] = $routeCallback BindTo ($this, __class__); } Public Function Dispatch ($currentPath) { foreach ($this->routes as $routePath = + $callback) { if ($ Routepath = = = $currentPath) { $callback (); } } Header (' http/1.1 '. $this->responsestatus); Header (' Content-type: '. $this->responsecontenttype); Header (' Content-length: '. Mb_strlen ($this->responsebody)); echo $this->responsebody; }}
Note the Addroute method. It receives a routed address (for example,/users/josh) and a callback for a route. The dispatch () method receives a current HTTP request address and invokes the corresponding route callback. Magical place in line 11th, we bind the callback of the route to an instance of the current app class. This allows us to create a callback function that can manipulate the state of the app instance:
<?php$app = new app (); $app->addroute ('/users/josh ', function () { $this->responsecontenttype = ' Application/json;charset=utf8 '; $this->responsebody = ' {' name ': ' Josh '} ';}); $app->dispatch ('/users/josh ');
[Modern PHP] Chapter II new features of the five closures