Home > Article > Backend Development > PHP 5.3 closure syntax introduction function() use() {}_PHP tutorial
PHP 5.3 added closure syntax, also known as anonymous functions, allowing developers to declare inline functions and save them in variables. Although this syntax is a bit weird compared to JavaScript closures, it is a good addition to the PHP language
The code is as follows | Copy code |
/** * The code mentioned below runs successfully in PHP5.3 or above. */ function callback($callback) { $callback(); } //Output: This is a anonymous function. /n //Here we directly define an anonymous function for transfer. In previous versions, this was not available. //Now, this syntax is very comfortable and basically the same as JavaScript syntax. The reason why it is said to be basic is that you need to continue reading //Conclusion: A comfortable grammar will definitely be popular. callback(function() { print "This is a anonymous function. /n"; }); //Output: This is a closure use string value, msg is: Hello, everyone. /n //A closure is first defined here, this time there is a name on the household registration book... //use, a fresh guy... //As we all know, closure: the internal function uses the variables defined in the external function. //In PHP's newly opened closure syntax, we use use to use variables defined outside the closure. //Here we use the external variable $msg. After it is defined, its value is changed. After the closure is executed, the original value is output //Conclusion: For basic type parameters passed by value, the value of the closure use is determined when the closure is created. $msg = "Hello, everyone"; $callback = function () use ($msg) { print "This is a closure use string value, msg is: $msg. /n"; }; $msg = "Hello, everybody"; callback($callback); //Output: This is a closure use string value lazy bind, msg is: Hello, everybody. /n //Change the reference method, we use the reference method to use //You can find that the output this time is the value after the closure is defined... //This is actually not difficult to understand. We use it by reference, and the closure uses the address of the $msg variable //When the value at the address $msg is changed later, when the value of this address is output in the closure, it will naturally change. $msg = "Hello, everyone"; $callback = function () use (&$msg) { print "This is a closure use string value lazy bind, msg is: $msg. /n"; }; $msg = "Hello, everybody"; callback($callback); //Output: This is a closure use object, msg is: Hello, everyone. /n //The output in the closure is the previously copied object with the value Hello, everyone, followed by a reassignment of the name $obj. //You can think about it this way //1. obj is the name of the object Hello, everyone //2. The object Hello, everyone is used by the closure, and the closure generates a reference to the Hello, everyone object //3. obj is modified to the name of the Hello, everybody object //4. Note that the entity represented by the name obj has changed, not the Hello, everyone object, so the output of the natural closure is still the previous Hello, everyone $obj = (object) "Hello, everyone"; $callback = function () use ($obj) { print "This is a closure use object, msg is: {$obj->scalar}. /n"; }; $obj = (object) "Hello, everybody"; callback($callback); //Output: This is a closure use object, msg is: Hello, everybody. /n //Let’s follow the steps above and proceed step by step: //1. The obj name points to the Hello, everyone object //2. The closure generates a reference pointing to the Hello, everyone object //3. Modify the scalar value of the object pointed to by the obj name (i.e. Hello, everyone object) //4. Execute the closure, and the output will naturally be Hello, everybody, because there is actually only one real object $obj = (object) "Hello, everyone"; $callback = function () use ($obj) { print "This is a closure use object, msg is: {$obj->scalar}. /n"; }; $obj->scalar = "Hello, everybody"; callback($callback); //Output: This is a closure use object lazy bind, msg is: Hello, everybody. /n //What does the closure refer to? &$obj, the reference generated by the closure points to the address pointed to by the name $obj. //Therefore, no matter how obj changes, there is no escape.... //So, the output is the changed value $obj = (object) "Hello, everyone"; $callback = function () use (&$obj) { print "This is a closure use object lazy bind, msg is: {$obj->scalar}. /n"; }; $obj = (object) "Hello, everybody"; callback($callback); /** * A counter generator using closures * This is actually based on the example of closures introduced in python... * We can think about it this way: * 1. Each time the counter function is called, a local variable $counter is created, initialized to 1. * 2. Then create a closure, which generates a reference to the local variable $counter. * 3. The function counter returns the created closure and destroys the local variable, but at this time there is a reference to $counter from the closure, * It will not be recycled, so we can understand it this way. The closure returned by the function counter carries a free * Variables. * 4. Since each call to counter creates an independent $counter and closure, the returned closures are independent of each other. * 5. Execute the returned closure, increment the free state variable it carries and return it, and the result is a counter. * Conclusion: This function can be used to generate independent counters. */ function counter() { $counter = 1; return function() use(&$counter) {return $counter ++;}; } $counter1 = counter(); $counter2 = counter(); echo "counter1: " . $counter1() . " /n"; echo "counter1: " . $counter1() . " /n"; echo "counter1: " . $counter1() . " /n"; echo "counter1: " . $counter1() . " /n"; echo "counter2: " . $counter2() . " /n"; echo "counter2: " . $counter2() . " /n"; echo "counter2: " . $counter2() . " /n"; echo "counter2: " . $counter2() . " /n"; ?> |