Closure, Anonymous functions, also known as Anonymous functions, were introduced in php5.3. An anonymous function is a function without a defined name, that is, a closure. Keep this in mind to understand the definition of an anonymous function. For example, the following code (the file name is do.php)
1 2 3 4 5 6 7 8 9 10 11 | <?php
function A() {
return 100;
};
function B(Closure $callback )
{
return $callback ();
}
$a = B(A());
print_r( $a );
?>
|
Copy after login
here A() can never be used as a parameter of B, because A is not an "anonymous" function, so it should be changed to this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php
$f = function () {
return 100;
};
function B(Closure $callback )
{
return $callback ();
}
$a = B( $f );
print_r( $a );
<?
$func = function ( $param ) {
echo $param ;
};
$func ( 'hello word' );
|
Copy after login
implementation. Closure##Pass anonymous functions as parameters in ordinary functions, and they can also be returned. This implements a simple closure.
I will give you an example below. Three examples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?php
function printStr() {
$func = function ( $str ) {
echo $str ;
};
$func ( ' hello my girlfriend ! ' );
}
printStr();
function getPrintStrFunc() {
$func = function ( $str ) {
echo $str ;
};
return $func ;
}
$printStrFunc = getPrintStrFunc();
$printStrFunc ( ' do you love me ? ' );
function callFunc( $func ) {
$func ( ' no!i hate you ' );
}
$printStrFunc = function ( $str ) {
echo $str .'<br>';
};
callFunc( $printStrFunc );
callFunc( function ( $str ) {
echo $str ;
} );
|
Copy after login
Keywords that connect closures and external variables: USE
Closures can save some variables and values in the context of the code block in which PHP uses anonymous functions by default. The context variable of the code block cannot be called, but you need to use the use keyword
Let’s take a look at another example (ok, I’m short of money, I’m vulgar):
1 2 3 4 5 6 7 8 9 10 11 12 | <?php
function getMoney() {
$rmb = 1;
$dollar = 8;
$func = function () use ( $rmb ) {
echo $rmb ;
echo $dollar ;
};
$func ();
}
getMoney();
|
Copy after login
You can see it. Note that dollar is not declared in the use keyword, so it cannot be obtained in this anonymous function, so we should pay attention to this issue during development.
Some people may wonder whether the context can be changed in the anonymous function. variable, but I found that it seems not possible:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php
function getMoney() {
$rmb = 1;
$func = function () use ( $rmb ) {
echo $rmb .'<br>';
$rmb ++;
};
$func ();
echo $rmb ;
}
getMoney();
|
Copy after login
Well, it turns out that use refers to only a copy of the variable, but what if I want to fully reference the variable instead of copying it? To achieve this effect, just add an & symbol before the variable:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php
function getMoney() {
$rmb = 1;
$func = function () use ( & $rmb ) {
echo $rmb .'<br>';
$rmb ++;
};
$func ();
echo $rmb ;
}
getMoney();
|
Copy after login
Okay, so that the anonymous function can reference the context variable. If the anonymous function is returned to the outside world, the anonymous function will save it. The variables referenced by use cannot be obtained by the outside world, so the concept of 'closure' may be clearer
Let's change the above example based on the description:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?php
function getMoneyFunc() {
$rmb = 1;
$func = function () use ( & $rmb ) {
echo $rmb .'<br>';
$rmb ++;
};
return $func ;
}
$getMoney = getMoneyFunc();
$getMoney ();
$getMoney ();
$getMoney ();
|
Copy after login
Okay, so much, what if we want to call an anonymous function in a class? Go directly to the demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php
class A {
public static function testA() {
return function ( $i ) {
return $i +100;
};
}
}
function B(Closure $callback )
{
return $callback (200);
}
$a = B(A::testA());
print_r( $a );
|
Copy after login
A::testA() returns an unnamed funciton
.
The concept of binding
The Closure in the above example is just a global anonymous function. Okay, now we want to specify that a class has an anonymous function. Function. It can also be understood that the access scope of this anonymous function is no longer global, but the access scope of a class. Then we need to bind an anonymous function to a class. .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php
class A {
public $base = 100;
}
class B {
private $base = 1000;
}
$f = function () {
return $this ->base + 3;
};
$a = Closure::bind( $f , new A);
print_r( $a ());
echo PHP_EOL;
$b = Closure::bind( $f , new B , 'B');
print_r( $b ());
|
Copy after login
In the above example, the anonymous function f has this inexplicably. This keyword means that the anonymous function needs to be bound to the class.
Binding. After it is determined, it is as if there is such a function in A, but whether this function is public or private, the last parameter of bind indicates the callable scope of this function.
You have seen bindTo above, let’s take a look at the introduction on the official website
Closure::bind — Copy a closure and bind the specified $this object and class scope.
Description
public static Closure Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
This method is
Closure: Static version of :bindTo
(). Check out its documentation for more information.
Parameters
closure
Anonymous function that needs to be bound.
newthis
Requires an object bound to an anonymous function, or NULL to create an unbound closure.
newscope
The class scope you want to bind to the closure, or 'static' means no change. If an object is passed in, the type name of the object is used. Class scope is used to determine the visibility of private, protected methods of the $this object within the closure. (Note: You can pass in the class name or an instance of the class. The default value is 'static', which means no change.)
Return value:
Return a new Closure object or on failure Return FALSE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php
class A {
private static $sfoo = 1;
private $ifoo = 2;
}
$cl1 = static function () {
return A:: $sfoo ;
};
$cl2 = function () {
return $this ->ifoo;
};
$bcl1 = Closure::bind( $cl1 , null, 'A');
$bcl2 = Closure::bind( $cl2 , new A(), 'A');
echo $bcl1 (), "\n" ;
echo $bcl2 (), "\n" ;
|
Copy after login
Let’s look at an example to deepen our understanding:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?php
class A {
public $base = 100;
}
class B {
private $base = 1000;
}
class C {
private static $base = 10000;
}
$f = function () {
return $this ->base + 3;
};
$sf = static function () {
return self:: $base + 3;
};
$a = Closure::bind( $f , new A);
print_r( $a ());
echo PHP_EOL;
$b = Closure::bind( $f , new B , 'B');
print_r( $b ());
echo PHP_EOL;
$c = $sf ->bindTo(null, 'C');
print_r( $c ());
|
Copy after login
Let’s look at a demo again:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?php
class Animal {
private static $cat = "加菲猫" ;
private $dog = "汪汪队" ;
public $pig = "猪猪侠" ;
}
$cat = static function () {
return Animal:: $cat ;
};
$dog = function () {
return $this ->dog;
};
$pig = function () {
return $this ->pig;
};
$bindCat = Closure::bind( $cat , null, new Animal());
$bindDog = Closure::bind( $dog , new Animal(), 'Animal');
$bindPig = Closure::bind( $pig , new Animal());
echo $bindCat (),'<br>';
echo $bindDog (),'<br>';
echo $bindPig (),'<br>';
|
Copy after login
Through the above examples, in fact, anonymous binding It’s not difficult to understand.... We are looking at an extended demo (introducing trait features)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <?php
trait DynamicTrait {
public function call( $name , $args ) {
if ( is_callable ( $this -> $name )){
return call_user_func( $this -> $name , $args );
} else {
throw new \RuntimeException( "Method {$name} does not exist" );
}
}
public function set( $name , $value ) {
$this -> $name = is_callable ( $value )?
$value ->bindTo( $this , $this ):
$value ;
}
}
class Animal {
use DynamicTrait;
private $dog = '汪汪队';
}
$animal = new Animal;
$animal ->getdog = function () {
return $this ->dog;
};
echo $animal ->getdog();
|
Copy after login
For example, now we use the current shopping environment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <?php
class Cart {
const PRICE_BUTTER = 10.00;
const PRICE_MILK = 30.33;
const PRICE_EGGS = 80.88;
protected $products = array ();
public function add( $item , $quantity ) {
$this ->products[ $item ] = $quantity ;
}
public function getQuantity( $item ) {
return isset( $this ->products[ $item ]) ? $this ->products[ $item ] : FALSE;
}
public function getTotal( $tax ) {
$total = 0.00;
$callback = function ( $quantity , $item ) use ( $tax , & $total ) {
$pricePerItem = constant(CLASS . "::PRICE_" . strtoupper ( $item ));
$total += ( $pricePerItem * $quantity ) * ( $tax + 1.0);
};
array_walk ( $this ->products, $callback );
return round ( $total , 2);
}
}
$my_cart = new Cart;
$my_cart ->add('butter', 10);
$my_cart ->add('milk', 3);
$my_cart ->add('eggs', 12);
echo $my_cart ->getTotal(0.03);
|
Copy after login
Additional explanation: Closures can use USE Key connects external variables.
Summary: The characteristics of PHP closures can actually be used to achieve similar or even more powerful functions using CLASS, let alone the closures of js. I can only look forward to PHP's future
Closure support
improvements. However, anonymous functions are still quite useful. For example, when using functions such as preg_replace_callback, you don't need to declare the
callback function
externally. Proper use of closures can make code more concise and refined.
The above is the detailed content of Detailed explanation of closure usage examples in php. For more information, please follow other related articles on the PHP Chinese website!