[ModernPHP] Chapter 2 Closure of new features

Source: Internet
Author: User
[ModernPHP] Chapter 2 Closure of new features Closure


Closures and anonymous functions have appeared since PHP 5.3.0, which is my favorite and most commonly used PHP function. I heard these names very well (at least I thought so for the first time), but in fact they are really easy to understand. They are the most useful tools required by every PHP developer's toolbox.


As a function, the closure encapsulates the external state during creation. Even if the environment does not exist when the closure is initially created, the encapsulation state will be stored in the closure all the time. This is a very difficult concept to grasp. once you can understand it, it feels like you have opened a new chapter in your life.


An anonymous function is actually a function without a name. Anonymous functions can be assigned to variables and passed in the code like all other PHP Objects. But it is still a function, so you can call it and pass parameters. The biggest use of an anonymous function is the callback of a function or method.


Closures and anonymous functions are theoretically different concepts. However, PHP thinks they are the same thing. Therefore, when I talk about closures, it may also refer to anonymous functions, and vice versa.


PHP closures and anonymous functions have the same syntax as functions, but do not confuse them. They are actually objects disguised as functions. If you print and check the type of a PHP Closure or anonymous function, you will find that they are all Closure class instances. Closure can be considered as an important data type as string and integer.


Create


We all know that PHP closures and functions look very similar. When you create a PHP closure like in example 2-19, you will not be surprised.


Example 2-19 simple closure

 "Hello Josh"

That's simple. In example 2-19, a Closure object is created and assigned to the variable $ closure. It looks like a standard PHP function: it uses the same syntax, receives parameters, and returns values. But it has no name.


We can call the $ closure variable. because $ closure is a Closure, the closure object implements the \ _ invoke () magic method. When the variable name is followed by a pair of () symbols, PHP will automatically find and call the _ invoke () method.


I usually use PHP closure objects as callback for functions and methods. Many PHP functions use callback functions, such as array_map () and preg_replace_callback (). This is like a customized function for PHP anonymous functions! Remember, just 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

 [2, 3, 4]

Doesn't it look so impressive? But remember, before the closure function is available, PHP developers have no good options. they can only create a named function and pass the function name as a parameter. In this way, the execution will be slow. The most important thing is that it separates the implementation and use of callback. Old PHP developers use the following code:


   
The above code can be executed normally, but there is no conciseness in example 2-20. We do not need a one-time function named incrementNumber () as a callback. You can use closures as callback to create code that is more concise and readable.


Attachment status


So far, we have demonstrated how to use an anonymous function as a callback. Next, let's look at how to use the PHP closure to attach and encapsulate the status. JavaScript developers may be confused about the closure of PHP, because the closure of PHP does not automatically encapsulate the state of the application to the closure like JavaScript. Instead, you must manually call the bintTo () method or use keyword of the closure object to attach the state to a PHP closure.


We usually use the use keyword to attach the closure state, so let's take this as an example (example 2-21 ). When you use the use keyword to attach a variable to a closure, the attached variable value remains the value of the moment when the variable is attached to the closure.


Example 2-21 use the use keyword to attach a closure State

  "Clay, get me sweet tea! "

In example 2-21, the named function enclosePerson () receives a $ name parameter and returns a closure object that encapsulates the $ name parameter. Even if the closure finally leaves the scope of the enclosePerson () function, the returned closure object $ clay still retains the value when the $ name parameter is attached to the closure. That is to say, the $ name variable still exists in the closure!


You can use the use keyword to pass multiple parameters to the closure. Parameters are separated by commas (,), just like the parameters of functions or methods in PHP.


Don't forget that PHP closures are all objects. Each closure instance has its internal state. we can use the $ this keyword like other PHP Objects to obtain these states. The default state of a closure object is quite boring. it contains a magic method _ invoke () and a bindTo () method. that's all.


However, the bindTo () method can lead us to explore 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 critical. it specifies the class of the object to which the closure is bound. In this way, we can get the member variables 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 reference an application object, as shown in example 2-22.


Example 2-22 use the bindTo method to attach the closure State

  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 route address (for example,/users/josh) and a route callback. The dispatch () method receives an HTTP request address and calls the corresponding route callback. The magic is in row 11th. We bound the callback of the route to the instance of the current App class. In this way, we can create a callback function that can operate the App instance status:

  addRoute('/users/josh', function () {    $this->responseContentType = 'application/json;charset=utf8';    $this->responseBody = '{"name": "Josh"}';});$app->dispatch('/users/josh');

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.