美文网首页
PHP闭包的理解是使用

PHP闭包的理解是使用

作者: 云龙789 | 来源:发表于2019-02-25 11:45 被阅读6次

    其实学习一个新的概念,除了知道怎么使用,更多的我是想知道它的使用场景。应用场景才是设计的根源。而对于PHP闭包的讲解,大多都是讲解的例子,但是只知道怎么用,还是不知道用在什么时候。这种情况你是不能灵活使用这个知识点的。

    • 以下总结来自于上面推荐文章的总结,但是我觉得是有道理的

    1.面向对象变成语言代码的复用主要采用继承来实现,而函数的复用,就是通过闭包来实现。这就是闭包的设计初衷。
    2.闭包可以在函数里面访问指定域上午变量,在PHP里使用use关键字来实现。
    3.php会自动把闭包函数转换成内置类 Closure 的对象实例,依赖 Closure 的对象实例又给闭包函数添加了更多的能力。
    4.Closure::bind 复制一个闭包,绑定指定 this 对象和类作用域。
    5.Closure::bindTo 复制当前闭包对象,绑定指定的 this对象和类作用域。

    • demo.php
    class Person
    {
        public $name = 'test';
    
        public function setName($name)
        {
            $this->name = $name;
        }
    
        public function getName()
        {
            return  $this->name;
        }
    }
    
    $closure = function () {
        return $this->name;
    };
    
    $person = new Person();
    $bindTo =$closure->bindTo($person);
    echo $bindTo(); //test
    echo '<br>';
    $bind = Closure::bind($closure,$person);
    echo($bind());//test
    echo '<br>';
    $person->setName('new test');
    echo $bindTo(); // 'new test'
    echo '<br>';
    echo($bind()); //'new test'
    
    demo打印结果

    注意

    bindTo -- 是将当前闭包 bindTo(绑定到) 对象
    bind -- 是将闭包绑定到对象,第一个参数是闭包,第二个参数是对象
    Closure::bind Closure::bindTo 都是闭包的特性,而不是对象
    bind 的第二个参数和 bindTo的第三个参数 newscope,是关联到匿名函数的类作用域,或者 'static' 保持当前状态。如果是一个对象,则使用这个对象的类型为心得类作用域。 这会决定绑定的对象的 保护、私有成员 方法的可见性。所以这个对象其实是 class 与 {} 中间的对象名,而不是实例化的那个变量。如果你是在对象中写,可以直接使用 CLASS 表示这个参数。如果不添加这个参数,则不能使用对应的 private、protect 方法或者属性

    • Moderm PHP 对比包的讲解

    1.理论上闭包和匿名函数是不同的概念。不过,PHP将其视作相同的概念。所以在PHP语言中闭包其实就是匿名函数
    2.PHP闭包和匿名函数的句法和普通函数相同,闭包和匿名函数其实是伪装成函数的对象,它们是Closure 类的实例。闭包和字符串或者整数一样,也是一等值类型。
    3.我们之所以能够调用 $closure 变量,使用为这个变量的值是一个闭包,而且闭包对象实现了 _invole() 魔术方法,只要变量后有(),PHP就会查找并调用 _invoke() 方法

    1. PHP闭包是对象。与人任何其他PHP对象类似,每个闭包实例都可以使用 $this 关键字获取闭包的内部状态。闭包对象的默认状态没什么用,不过有一个 __invoke() 魔术方法和一个bindTo()方法,仅此而已
      5.但是,bindTo() 方法为闭包增加了一些有趣的潜力,我们可以使用这个方法把 Closure 对象的内部状态绑定到其他对象上,bindTo(),方法的第二个参数很重要,其作用是指定绑定闭包的那个对象所属的PHP类。因此,闭包可以访问绑定闭包的对象中收保护和私有的成员变量。
      6.你会发现,PHP框架经常使用bindTo()方法把路由URL映射到匿名回掉函数上。框架会把匿名函数绑定到应用对象上,这么做,可以在这个匿名函数中使用$this关键字引用重要的应用对象。
    <?php
    
    class App
    {
        protected $routes = [];
        protected $responseBody;
    
        public function addRoute($path, Closure $callback)
        {
            $this->routes[$path] = $callback->bindTo($this,'App');
        }
    
        public function dispatch($currentPath)
        {
            foreach ($this->routes as $path => $callback) {
                if ($path == $currentPath) {
                    echo $callback();
                }
            }
        }
    
        public function getResponse()
        {
            return $this->responseBody;
        }
    }
    
    $app = new App();
    $app->addRoute('test', function () {
        $this->responseBody = 'test path';
    });
    
    $app->addRoute('name', function () {
        $this->responseBody = 'name path';
    });
    
    $app->dispatch('test');
    echo $app->getResponse(); // test path
    echo '<br>';
    $app->dispatch('name');
    echo $app->getResponse(); //test path
    
    

    当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
    也就是只要一个对象的变量(比如以下的$adder) 加上一个 (),其实就会调用 __invoke()方法。
    而闭包,就相当于是 Closure 类的 __invoke() 方法

    • Closure::call function call ($newThis, ...$parameters) {}
      Closure::call — Binds and calls the closure(绑定一个类,并返回闭包) ----- PHP>=7.0
    第一个参数是类的实例化,第二个参数是  __construct() 的参数,return 返回的结果是闭包中返回的结果。
    demo 还是上面的那个
    
    $callback = function(){
        return $this->responseBody = 'test path';
    
    };
    $app = new App();
    $app->addRoute('test', $callback);
    
    echo $callback->call($app);
    
    • _invoke() 魔术方法的使用
    <?php
    
    class Add {
        public $left;
        public $right;
    
        public function construct($left = 0, $right = 0) {
            $this->left  = $left;
            $this->right = $right;
        }
    
        public function __invoke() {
            return $this->left + $this->right;
        }
    }
    
    $adder = new Add;
    
    $adder->left  = 1;
    $adder->right = 2;
    echo $adder(); // 3
    
    $adder->left  = 3;
    echo $adder(); // 5
    

    相关文章

      网友评论

          本文标题:PHP闭包的理解是使用

          本文链接:https://www.haomeiwen.com/subject/pypwyqtx.html