【问题标题】:php acces to properties of a containing objectphp 访问包含对象的属性
【发布时间】:2012-07-30 06:40:42
【问题描述】:

我有一个小问题。在 javascript 中可以转发范围:

var aaa = new function () {
    that = this;
    that.bbb  = 'foo';
    this.ccc = new function () {
        this.ddd = 'bar';
        this.eee = function () {
            return that.bbb+this.ddd;
        }
    }
}

aaa.ccc.eee() 将返回 'foobar'。 我怎样才能在 PHP 中做一些具有相同效果的事情?我有一个代码:

class bbb {
    public $ccc = 'bar';
        function __construct () {
            echo($that->aaa.$this->ccc);
        }
}
class aaa {
    public $that;
    public $aaa = 'foo';
    public $bbb;
    function __construct () {
        echo($this->aaa);
        $this->$bbb = new bbb();
        $this->$that = $this;
    }
}
$a = new aaa ();

我可以使用类似的东西吗:

$this->bbb = new bbb ($this);

class bbb {
    public $that;
    function __contruct ($parent) {
        $that = $parent
        ....
    }
}

?

【问题讨论】:

  • 你应该先从php.net/oop开始
  • 虽然它们在某些地方的语法相似,但将 Javascript 与 PHP 进行比较是一个BIG 错误,它们是完全不同的野兽。 Javascript 是一种无类的 OO 语言,PHP 是一种提供一些非常有限的 OO 支持的脚本语言。您展示的 Javascript 代码以 PHP 无法做到的方式创建了 2 个匿名对象。可以假装使用闭包继承范围,但是您需要在声明函数时命名要继承的变量,实际上它所做的只是通过引用将它们传递给对象。
  • @DaveRandom 这些(语法或其他方面)没有任何相似之处,PHP 的类最接近 js 中的原型,而 PHP 的闭包最接近这个 js 怪物
  • @Esailija 我的意思是 Javascript 和 PHP 通常在某些地方在语法上是相似的,而不是上面的两个代码示例。当然,上面的 Javascript 是一种奇怪的处理方式,我想知道对象文字有什么问题?
  • @DaveRandom 啊,我误会你了,我以为你在说这些作品。

标签: php oop object scope this


【解决方案1】:

没有什么能阻止你做与你的 JS 代码完全相同的事情,尽管这不是你在 PHP 中每天都能看到的:

PHP 5.3

$aaa = (object)array(
    'bbb' => 'foo',
    'ccc' => (object) array(
        'ddd' => 'bar',
        'eee' => function() use(&$aaa){ $self = $aaa->ccc; return $aaa->bbb.$self->ddd; }
    ),
);

echo call_user_func($aaa->ccc->eee);

请注意,在 PHP 5.3 中,无法在闭包内使用变量 $this,因此您必须从导入的变量之一(在本例中为 $aaa)开始获取必要的上下文。

另外,请注意您不能使用$aaa-ccc->eee()“直接”调用函数,因为 PHP 很烂:$aaa->cccstdClass 类型的对象,并且该类没有正式成员命名为eee

我在这里也很“可爱”,通过引用捕获$aaa,它可以在一行中定义整个对象图(如果需要在一个语句中定义没有闭包的情况下通过值捕获$aaa,然后在另一个中添加了$aaa->ccc->eee = function() ... 的闭包)。

PHP 5.4

$aaa = (object)array(
    'bbb' => 'foo',
    'ccc' => (object) array(
        'ddd' => 'bar',
        'eee' => function() use(&$aaa) { return $aaa->bbb.$this->ddd; }
    ),
);

$aaa->ccc->eee = $aaa->ccc->eee->bindTo($aaa->ccc);
echo call_user_func($aaa->ccc->eee);

在 PHP 5.4 中,可以在闭包内使用 $this,只要您先用 bindTo “重新绑定”它。由于前面提到的相同原因,您不能在定义闭包的同时这样做:PHP 很烂。

【讨论】:

  • 你不能直接调用分配给对象属性的匿名函数,这很糟糕。我真的希望这会在 5.4 中得到解决,我有一个我使用 很多 的类,我真的希望有一个名为 list() 的方法,但我不能这样做,因为 @ 987654335@ 是一种语言结构。在构造函数中创建一个匿名函数是显而易见的解决方法,但它不起作用(!!!) - 太烦人了。
  • @DaveRandom 你总是可以从一个定义了处理它的神奇__call 方法的类中扩展这些对象。
  • @DaveRandom:我本来打算给你 Esailija 的回复,但他打败了我 :) 不幸的是,如果你这样做了,你就不能使用 (object) 转换技巧,因为它总是转换为 stdClass .
  • 你知道,我写了一个使用__call() yesterday 的课程,但我从未实现过这种飞跃。你不会看到我 10 分钟,而我去做那件事我一直很生气,我不能做 2 年。虽然我还是觉得你做不到很傻。
  • @Esailija:+1 因为为什么不:)
【解决方案2】:
class bbb {
    function __construct ($parrent) {
        echo $parrent->ccc;
    }
}

class aaa {
    public $aaa = 'foo';
    public $bbb;
    public $ccc = 'bar';

    function __construct () {
        echo $this->aaa;
        $this->bbb = new bbb($this);
    }
}

$a = new aaa();

【讨论】:

    【解决方案3】:

    您在 javascript 中所做的与您在 PHP 中所做的完全不同。在 javascript 中,您正在执行闭包,而在 PHP 中,您正在执行一些格式错误的类。

    在 PHP 中,最接近的等价物是(尽管因为没有 IIFE 等而丑陋)

    $tmp = function() {
        $that = new stdClass();
        $that->bbb = "foo";
    
        $tmp = function() use ($that) {
            $this_ = new stdClass();
            $this_->ddd = "bar";
            $this_->eee = function() use ($that, $this_) {
                return $that->bbb . $this_->ddd;
            };
            return $this_;
        };
        $that->ccc = $tmp();
        return $that;
    };
    
    $aaa = $tmp();
    
    var_dump( call_user_func( $aaa->ccc->eee ));
    //string(6) "foobar"
    

    在 php 5.4.5 中测试。

    【讨论】:

      猜你喜欢
      • 2011-03-09
      • 2012-01-01
      • 2023-02-01
      • 1970-01-01
      • 2023-03-23
      • 2012-10-08
      • 2016-05-12
      相关资源
      最近更新 更多