Today I’ll write an article about closures in PHP. PHP has added support for anonymous functions since version 5.3, and through several iterations to PHP5.6 and PHP7, closures in the PHP language have been perfected. Combined with the event-driven support provided by Swoole, PHP closures are very powerful and elegant.

Anonymous functions

At the heart of closures are anonymous functions, which in PHP are actually objects of a Closure class. Unlike normal object-oriented programming, the code for anonymous functions is written directly at the call point, without the need to write an extra class to code the method. This has the advantage of being more direct. The following example sets a timer that prints Hello World every 2 seconds.

The traditional writing

function timer () {
    echo "hello world";
}
Swoole\Timer::tick(2000, 'timer');
Copy the code

The closure of writing

Swoole\Timer::tick(2000, function () {
    echo "hello world";
});
Copy the code

The traditional way of writing a non-closure is to declare a function and then pass in the function name string. The two pieces of code are separate and not intuitive. The closure of the declaration of the timer and the timer to execute the code written together, logic is very clear and intuitive. Using closure syntax makes it easy to write callback functions. Closures can be written elegantly in event-driven programming, sorting, array_walk, and other scenarios that require the user to pass in a piece of execution code.

Closures are even more powerful because they can introduce external variables directly at the invocation point. The method implemented in PHP is the use keyword.

The Use of grammar

If the timer needs to pass in a variable, the traditional way to write it is through a global variable. Unlike JS, PHP’s variable import is explicit, and references to external variables must be declared using use. While JS is implicit, anonymous functions can be manipulated inside the external variables, without declaration. The upside is less code, but the downside is risk and confusion.

The traditional writing

$str = "hello world";
function timer () {
    global $str;
    echo $str;
}
Swoole\Timer::tick(2000, 'timer');
Copy the code

The closure of writing

$str = "hello world";
Swoole\Timer::tick(2000, function () use ($str) {
    echo $str;
});
Copy the code

The closure notation uses use to introduce the current $STR variable directly, without using the global variable. And if it is in swoole event-driven programming model, using the global couldn’t realize asynchronous concurrent, because global global variables, only one, if there are multiple client requests at the same time, each request to query the database, the output of different content, traditional programming method is not easy to implement, need to use global variables, arrays, The client ID is used as the KEY to save data.

The traditional writing

$requestArray = array();
$dbResultArray = array();

function my_request($request, $response) {
    global $dbResultArray, $requestArray;
    $queryId = $db->query($sql, 'get_result');
    $requestArray[$request->fd] = array($request, $response);
    $dbResultArray[$queryId] = $request->fd;
}

function get_result($queryId, $queryResult) {
    global $dbResultArray, $requestArray;
    list($request, $response) = $requestArray[$dbResultArray[$queryId]];
    $response->end($queryResult);
}

$server->on('request', 'my_request');
Copy the code

The closure of writing

$server->on('request', function ($request, $response) {
    $queryId = $db->query($sql, function ($queryId, $queryResult) use ($request, $response) {
        $response->end($queryResult);
    });
});
Copy the code

The traditional approach is very complex and requires saving/extracting data from the global array multiple times. Closures, on the other hand, are neat and elegant, achieving the same functionality in just a few lines of code. Closure writing is ideal for writing asynchronous, non-blocking callback server programs. PHP and JS are the only popular programming languages with this capability.

Closures have more features

Use anonymous functions in class methods, not introduced with use in versions 5.4 and above

This can be used directly in anonymous functions

This can be used directly in anonymous functions to call methods on the current object. In swoole programming, you can use this feature to reduce the use-in-pass of the $serv object.

class Server extends Swoole\Server { function onReceive($serv, $fd, $reactorId, $data) { $db->query($sql, function ($queryId, $queryResult) use ($fd) { $this->send($fd, $queryResult); }}}Copy the code

In addition, if you want to modify an external variable in a closure function, you can add the & reference symbol to the variable when using. Note that object types do not require ampersand, because objects in PHP pass references, not values, by default.

As long as you can guarantee your salary to rise a step (constantly updated)

I hope the above content can help you. Many PHPer will encounter some problems and bottlenecks when they are advanced, and they have no sense of direction when writing too many business codes. I have sorted out some information, including but not limited to: Distributed architecture, high scalability, high performance, high concurrency, server performance tuning, TP6, Laravel, YII2, Redis, Swoole, Swoft, Kafka, Mysql optimization, shell scripting, Docker, microservices, Nginx and many other knowledge points can be shared free of charge to everyone, you can join my PHP technology exchange group 953224940

>>> Architect growth path