Interviewer: Do you know the core feature of PHP-anonymous functions? Say something

put forward

Before anonymous functions appeared, all functions needed to be named before they could be used

function increment($value)
{
    
    
    return $value + 1;
}

array_map('increment', [1, 2, 3]);

Sometimes the function may only need to be used once. At this time, using anonymous functions will make the code more concise and intuitive, and at the same time avoid the function from being used in other places

array_map(function($value){
    
    
    return $value + 1;
}, [1, 2, 3]);

Definition and use

PHP treats closures and anonymous functions as equivalent concepts (collectively referred to as anonymous functions in this article), which are essentially objects masquerading as functions.

The essence of an anonymous function is an object, so just like an object, an anonymous function can be assigned to a variable

$greet = function(string $name){
    
    
    echo "hello {
      
      $name}";
}

$greet("jack") // hello jack

All anonymous functions are instances of Closure objects

$greet instanceof Closure // true

Objects have no parent scope, so you need to use use to manually declare the variables used.

$num = 1;
$func = function() use($num){
    
    
    $num = $num + 1;
    echo $num;
}
$func();  // 2
echo $num;  // 还是 1

If you want the variables in the anonymous function to take effect, you need to pass by value by reference

$num = 1;
$func = function() use(&$num){
    
    
    $num = $num + 1;
    echo $num;
}
$func();  // 2
echo $num;  // 2

Starting from PHP 5.4, when an anonymous function is used in a class, the $this of the anonymous function will be automatically bound to the current class

class Foo {
    
    
    public function bar()
    {
    
       
        return function() {
    
    
            return $this;
        };
    }
}

$foo = new Foo();
$obj = $foo->bar(); // Closure()
$obj();   // Foo

If you don’t want automatic binding to take effect, you can use static anonymous functions

class Foo {
    
    
    public function bar()
    {
    
       
        return static function() {
    
    
            return $this;
        };
    }
}
$foo = new Foo();
$obj = $foo->bar(); // Closure()
$obj();   // Using $this when not in object context

The essence of anonymous functions

The essence of anonymous functions is the Closure object, including the following five methods

Closure {
    
    
    private __construct ( void )
    public static bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] ) : Closure
    public bindTo ( object $newthis [, mixed $newscope = "static" ] ) : Closure
    public call ( object $newthis [, mixed $... ] ) : mixed
    public static fromCallable ( callable $callable ) : Closure
}

__construct -Prevent anonymous functions from being instantiated

$closure = new \Closure();
// PHP Error:  Instantiation of 'Closure' is not allowed

Closure::bindTo-Copy the current anonymous function object, bind the specified $this object and class scope. In layman's terms, it is to manually bind the anonymous function to the specified object. With this, the function of the object can be extended.

// 定义商品类
class Good {
    
    
    private $price;

    public function __construct(float $price)
    {
    
    
        $this->price = $price;
    }
}

// 定义一个匿名函数,计算商品的促销价
$addDiscount = function(float $discount = 0.8){
    
    
    return $this->price * $discount;
}

$good = new Good(100);

// 将匿名函数绑定到 $good 实例,同时指定作用域为 Good
$count = $addDiscount->bindTo($good, Good::class); 
$count(); // 80

// 将匿名函数绑定到 $good 实例,但是不指定作用域,将无法访问 $good 的私有属性
$count = $addDiscount->bindTo($good); 
$count(); // 报错

Closure::bind - bindTo The static version of the method can be used in two ways:

Usage 1: achieve the same effect as the bindTo method

$count = \Closure::bind($addDiscount, $good, Good::class); 

Usage 2: Bind anonymous functions to classes (not objects), remember to set the second parameter to null

// 商品库存为 10
class Good {
    
    
    static $num = 10;
}

// 每次销售后返回当前库存
$sell = static function() {
    
    
    return"当前库存为". --static::$num ;
};

// 将静态匿名函数绑定到 Good 类中
$sold = \Closure::bind($sell, null, Good::class);

$sold(); // 当前库存为 9
$sold(); // 当前库存为 8

call- PHP 7 new callways to achieve binding and call the anonymous function, in addition to more concise syntax, but also higher performance

// call 版本
$addDiscount->call($good, 0.5);  // 绑定并传入参数 0.5,结果为 50

// bindTo 版本
$count = $addDiscount->bindTo($good, Good::class); 
$count(0.5); // 50

fromCallable- given callablefunction transforming into anonymous function

class Good {
    
    
    private $price;

    public function __construct(float $price)
    {
    
    
        $this->price = $price;
    }
}

function addDiscount(float $discount = 0.8){
    
    
    return $this->price * $discount;
}

$closure = \Closure::fromCallable('addDiscount');
$good = new Good(100);
$count = $closure->bindTo($good);  
$count = $closure->bindTo($good, Good::class);   // 报错,不能重复绑定作用域
$count(); // 报错,无法访问私有属性

fromCallable Equivalent to

$reflexion = new ReflectionFunction('addDiscount');
$closure = $reflexion->getClosure();

One thing that needs special attention here is that whether it is a closure converted from fromCallable or a closure obtained using reflection, when using bindTo, if the second parameter specifies the binding class, an error will be reported

Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()

Pay attention, don't get lost

Alright, everyone, the above is the entire content of this article. The people who can see here are all talents . As I said before, there are a lot of technical points in PHP, because there are too many, it is really impossible to write, and you will not read too much after writing it, so I will organize it into PDF and documents here, if necessary Can

Click to enter the secret code: PHP+「Platform」

Insert picture description here

Insert picture description here


For more learning content, please visit the [Comparative Standard Factory] excellent PHP architect tutorial catalog, as long as you can read it to ensure that the salary will rise a step (continuous update)

The above content hopes to help everyone . Many PHPers always encounter some problems and bottlenecks when they are advanced. There is no sense of direction when writing too much business code. I don’t know where to start to improve. I have compiled some information about this, 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 scripts, Docker, microservices, Nginx, etc. Many knowledge points, advanced advanced dry goods, can be shared with everyone for free, and those who need can join my PHP technology exchange group

Guess you like

Origin blog.csdn.net/weixin_49163826/article/details/109170089