📜 ⬆️ ⬇️

Lambda functions and closures

image Of course, many of us are familiar with this concept, but this article is designed for beginners. In this post I will try to consider this phenomenon and give examples of use. First you need to understand what is the lambda function. So, the lambda function, it is often called anonymous, that is, the function in the definition of which does not need to specify its name. The return value of such a function is assigned to a variable, through which this function can be called later.
Before the release of PHP 5.3, it was possible to define lambda functions, but they could not be called complete. Now I will give a couple of examples and continue to consider these concepts.
<?php $temp = create_function( '$match', 'return (preg_match(\'/^{(.*)}$/\',$match[1],$m) ? "cms_$m[1]" : $match[1]);'); $query = 'SELECT * FROM {documents}'; $regExp = '/([^{"\']+|\'(?:\\\\\'.|[^\'])*\'|"(?:\\\\"|[^"])*"|{[^}{]+})/'; echo preg_replace_callback($regExp, $temp, $query); // SELECT * FROM cms_documents ?> 

Of course, dynamic creation of functions does not solve all the problems, but sometimes writing such a one-time function can be useful. You can extend our example:
 <?php class Builder { private $query; private $prefix; public function __construct($prefix='' ) { $this->query = $query; $this->prefix = $prefix; } public function replaceCallback( $match ) { return ( preg_match('/^{(.*)}$/',$match[1],$m) ? ( empty($this->prefix) ? $m[1] : "{$this->prefix}_$m[1]" ) : $match[1] ); } public function build($query) { static $regExp = '/([^{"\']+|\'(?:\\\\\'.|[^\'])*\'|"(?:\\\\"|[^"])*"|{[^}{]+})/'; return preg_replace_callback($regExp, array(&$this, "replaceCallback"), $query); } }; $builder = new Builder('cms'); echo $builder->build(“SELECT * FROM {documents}”); // SELECT * FROM cms_documents ?> 

The concept of closure is probably familiar to JavaScript programmers, as well as programmers in many other languages. A closure is a function that covers or closes the current scope. To understand all this, consider an example:
 <?php $x = function( $number ) { return $number * 10; }; echo $x(8); //  80 ?> 

As you may have noticed, the function has no name and the result is assigned to the variable. A lambda function created in this way returns a value as an object of type closure.
In PHP 5.3, it became possible to call objects as if they were functions. Namely, the magic __invoke () method is called each time a class is called as a function.
Variables are not available inside the function unless they are declared global, and variables from the child context are not available unless the use keyword is used. Typically, in PHP, variables are passed to the closure by value; this behavior can be changed using the ampermsand in front of the variable in the use expression. Consider an example:
 <?php class ClosureTest { public $multiplier; public function __construct( $multilier ) { $this->multiplier = $multilier; } public function getClosure() { $mul = &$this->multiplier; return function( $number ) use( &$mul ) { return $mul * $number; }; } } $test = new ClosureTest(10); $x = $test->getClosure(); echo $x(8); //  80 $test->multiplier = 2; echo $x(8); //  16 ?> 

If you remove the ampersands, then both times will be displayed 80, because the variable $ mul inside the closure will be a copy, not a reference.
So, it remains only to find out how this can be applied in practice.
Consider an example:
 <?php class QueryBuilder extends Builder { public function getQueryObject($query) { $self = $this; return function() use ($self,$query) { $argv = func_get_args(); foreach ( $argv as $i => $arg ) $argv[$i] = mysql_escape_string($arg); array_unshift($argv, $self->build($query)); return call_user_func_array( “sprintf”, $argv); }; } }; $builder = new QueryBuilder(); $deleteBook = $builder->getQueryObject(“DELETE FROM {documents} WHERE id=%d”); $deleteBook( $_GET['id'] ); ?> 

This example can already be used for fairly flexible prototyping. It is enough to declare methods for all SQL operations with the object.
The author does not urge everyone to adhere to this practice, nor does he think that it’s better, all of the above is just an example of use, and perhaps not the most technical and interesting, and nothing more.
UPD Speaking about the longest regular expression, I did not sign it in the comments and decided to bring it here. It only searches for strings in single and double quotes, as well as table names and escapes them.

')

Source: https://habr.com/ru/post/121976/


All Articles