1. Overview
Closures and anonymous functions are introduced in PHP 5.3.0, and these two features are very useful and should be mastered by every PHP developer.
Closures are functions that encapsulate the surrounding state at the time of creation, even if the closure's environment does not exist, the encapsulated state in the closure still exists.
Anonymous functions are actually functions with no names, and anonymous functions can be assigned to variables, and can be passed like any other PHP function object. However, the anonymous function is still a function, so you can call it, and you can pass in the parameter, which is appropriate for the callback as a function or method.
Note: In theory, closures and anonymous functions are different concepts, but PHP regards them as the same concept (anonymous functions are also called closure functions in PHP), so the following refers to the closure of the anonymous function, and vice versa.
2. Create closure
Creating closures is simple:
<?php
$greet = function ($name) {
Return sprintf ("Hello%s\r\n", $name);
};
echo $greet (' 111cn.net ');
Results Print:
Hello 111cn.net
Closures and ordinary PHP functions are similar: commonly used syntax is the same, also accept parameters, and can return a value. However, the closure does not have a function name.
Note: The reason we can call the $greet variable is because the value of the variable is a closure, and the closure object implements the __invoke () Magic method, as long as the variable name has (), PHP will find and invoke the __invoke method.
We usually use the PHP closure as a function of the callback method, in fact, many PHP functions will use closures, such as Array_map and Preg_replace_callback, this is the best time to use PHP anonymous functions. Remember that closures, like other values, can be passed into other PHP functions as arguments:
<?php
$numberPlusOne = Array_map (function ($number) {
return $number + + 1;
}, [1, 2, 3]);
Print_r ($numberPlusOne);
Before the closure occurs, the PHP developer can only create a named function, and then use the name to refer to this function:
<?php
function Incrementnumner ($number) {
return $number + + 1;
}
$numberPlusOne = Array_map (' Incrementnumber ', [1, 2, 3]);
Print_r ($numberPlusOne);
Doing so separates the implementation of the callback from the site where it is used, and it is simpler to implement the code with the closure.
3, inherit the variable from the parent scope
In PHP, you must manually invoke the BindTo method of the closure object or append the parent scope's variables and states to the PHP closure using the USE keyword. But in the actual application, also uses the USE keyword Realization majority.
Use keyword
In fact, the Laravel framework also uses a lot of closures, most commonly such as routing definitions:
Route::group ([' domain ' => ' {account}.myapp.com '], function () {
Route::get (' User/{id} ', function ($account, $id) {
//
});
});
The two function in this box is a closed package. The use scenario of inheriting variables from the parent scope is also are cheap in the laravel underlying source code, such as the Saveorfail method of model.php (illuminate\database\eloquent):
Closure-use
The purpose of this method is to use the transaction to save the model data to the database, where we use the closure to return the saved state, while using the USE keyword to pass the $options of the parent scope to the closure so that it can access the data.
In addition, it is also supported to pass multiple parent scope variables to closures, such as the Forcefill method in the model class:
Closure-use-multi
Multiple variables are separated by commas.
BindTo method
As we mentioned earlier, closures are an object, so we can use the $this keyword in the closure to get the internal state of the closure, the default state of the closure object is useless, and the __invoke Magic method and BindTo method should be noted.
The role of __invoke has already been said that the __invoke () method is invoked automatically when an attempt is made to call an object in the form of a call to a function.
Let's look at the BindTo method, by which we can bind the inner state of the closure to other objects. The second parameter of the BindTo method is particularly important in that it specifies the PHP class that the object of the binding closure belongs to, so that the closure can access the protected and private member variables in the object of the state-bound closure elsewhere.
You will find that the PHP framework often uses the BindTo method to map routing URLs to anonymous callback functions, and the framework binds anonymous callback functions to application objects so that the $this keyword can be used to refer to an important Application object in an anonymous function:
<?php
Class App {
protected $routes = [];
protected $responseStatus = ' OK ';
protected $responseContentType = ' text/html ';
protected $responseBody = ' Laravel college ';
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;
}
}
Here we need to focus on the Addroute method, the parameter of which is a routing path and a routing callback, the parameter of the dispatch method is the path of the current HTTP request, and it invokes the matching routing callback. Line 9th is the focus, and we bind the routing callback to the current app instance. Doing so can handle the state of the app instance in the callback function:
$app = new app ();
$app->addroute (' User/nonfu ', function () {
$this->responsecontenttype = ' Application/json;charset=utf8 ';
$this->responsebody = ' {' name ': ' Laravelacademy '} ';
});
$app->dispatch (' User/nonfu ');
The BindTo method is also useful at the bottom of the larval, as detailed in the Illuminate\support\traits\macroable __call method: