【问题标题】:PHP equivalent of JavaScript bindPHP 等效于 JavaScript 绑定
【发布时间】:2015-01-16 20:13:14
【问题描述】:

首先请原谅我的英语我不是母语人士,如果看起来很粗糙,我很抱歉,这是我第一次在这个网站上发帖。 我认为我的问题很简单。比方说,我们有:

class A {

    function foo() {

        function bar ($arg){
            echo $this->baz, $arg;
        }

        bar("world !");

    }

    protected $baz = "Hello ";

}

$qux = new A;

$qux->foo();

在这个例子中,“$this”显然不是指我的对象“$qux”。

我应该怎么做才能让它引用“$qux”?

可能在 JavaScript 中:bar.bind(this, "world !")

【问题讨论】:

  • 为什么需要在php中嵌套函数?这是不好的做法
  • 只是因为我在这个函数中使用了两次相同的代码。
  • 然后按照@georg 的建议使用闭包

标签: javascript php bind equivalent


【解决方案1】:

实际上,$this 在该上下文中调用时确实引用了$qux

你不能在对象方法以外的上下文中使用$this,所以如果你采取这样的方式:

function test() {
    echo $this->baz;
}

不管你做什么,它都行不通。

【讨论】:

    【解决方案2】:

    PHP 没有嵌套函数,因此在您的示例中 bar 本质上是全局的。你可以通过使用闭包(=匿名函数)来实现你想要的,从 PHP 5.4 开始支持binding

    class A {
        function foo() {
            $bar = function($arg) {
                echo $this->baz, $arg;
            };
            $bar->bindTo($this);
            $bar("world !");
        }
        protected $baz = "Hello ";
    }
    
    $qux = new A;
    $qux->foo();
    

    UPD:但是,bindTo($this) 没有多大意义,因为闭包会自动从上下文继承 this(同样,在 5.4 中)。所以你的例子可以很简单:

        function foo() {
            $bar = function($arg) {
                echo $this->baz, $arg;
            };
            $bar("world !");
        }
    

    UPD2:对于 php 5.3- 这似乎只有通过像这样丑陋的 hack 才能实现:

    class A {
        function foo() {
            $me = (object) get_object_vars($this);
            $bar = function($arg) use($me) {
                echo $me->baz, $arg;
            };
            $bar("world !");
        }
        protected $baz = "Hello ";
    }
    

    这里get_object_vars() 用于“发布”受保护/私有属性,以使其在闭包中可访问。

    【讨论】:

    • PHP 有嵌套函数,但通常使用它们不是很明智stackoverflow.com/questions/415969/…
    • @Asped:没有。您可以在另一个函数中编写一个函数,但这不会使其嵌套。内部函数是全局的。
    • 嗯,好吧,我不知道
    • 好的,所以我使用了闭包,但使用变量而不是“$this”。我必须考虑 PHP
    • @user3292788:是的,这似乎是唯一的方法。在答案中添加了注释。
    【解决方案3】:

    这种方式有点奇怪,但是如果你在一个函数内部使用一个函数,那么当然有一些 closuers 是有效的。 你可以在javascript中遇到类似的问题。 我建议根本不要使用它们,但是如果由于某种原因您不想使用,那么我会尝试这样的事情(未经测试):

    class A {
    
        function foo() {
    
            $that = $this;
            function bar ($arg){
                echo $that->baz, $arg;
            }
    
            bar("world !");
    
        }
    
        protected $baz = "Hello ";
    
    }
    
    $qux = new A;
    
    $qux->foo();
    

    更新 如果嵌套函数充当全局函数,那么如果需要使用它,您可以将对象作为参数传递:

    函数 foo() {

            function bar ($o,$arg){
                echo $o->baz, $arg;
            }
    
            bar($this,"world !");
    
        }
    

    【讨论】:

      【解决方案4】:

      如果我理解您想要实现的目标,可能是这样的:

      <?php
      class Foo {
      
        public $prop;
      
        public function __construct($prop) {
          $this->prop = $prop;
        }
      
        public function __call($name, $arguments) {
          if (!isset($this->$name)) {
            throw new InvalidArgumentException("No such property: $name");
          }
      
          if (! $this->{$name} instanceof Closure) {
            throw new InvalidArgumentException("{$name} is not a closure");
          }
      
          $c = $this->{$name}->bindTo($this);
          return $c(...$arguments);
        }
      }
      
      $f = new Foo("bar");
      $f->bar = function ($arg) {
        print_r([$arg, $this->prop]);
      };
      
      $f->bar("A");
      ?>
      

      这样,您基本上可以对类中的任何函数进行猴子补丁并像本地一样调用它,甚至包括使用$this。但是有两个限制:

      • 这似乎毫无意义,因为 Traits 可用,除非您正在添加真正动态定义的不可修改包
      • 虽然闭包可以访问$this 上的属性,但它仍然在对象外部,因此只能访问公共属性。尝试访问 protected/private 属性将失败。

      【讨论】:

        猜你喜欢
        • 2013-07-15
        • 1970-01-01
        • 2010-12-29
        • 2010-10-21
        • 1970-01-01
        • 2014-10-20
        • 2015-01-04
        • 2013-10-01
        • 2011-07-08
        相关资源
        最近更新 更多