如何在 PHP 中访问包含对象的属性


how to access containing object's properties in PHP?

我正在编写一些PHP代码,其中一个对象("容器")保留指向另一个对象("内容")的指针。 问题是内容需要访问容器的方法或属性。

下面是我想做的一个简化示例:

class Container {
    function __construct($type, $contents) {
        $this->type = $type;
        $this->contents = $contents;
    }
    function display() {
        return $this->contents->display();
    }
}
class Contents {
    function __construct($stuff) {
        $this->stuff = $stuff;
    }
    function display() {
        return 'I am ' . $this->stuff . ' in '; // how to access Container here?
    }
}
$item = new Container('a can', new Contents('Prince Albert'));
echo $item->display() . "'n";
// Displays: I am Prince Albert in 
// Wanted: I am Prince Albert in a can

正确的方法是什么?

我尝试了几种有效的方法,但他们感觉不对。 例如:

  • 重新定义Contents::display()采用一个参数,这看起来并不优雅:

    function display($container) {
        return 'I am ' . $this->stuff . ' in ' . $container->type;
    }
    
  • Contents::display()中,我调用了debug_backtrace(true)来找出调用它的内容,然后从回溯信息访问对象。 这感觉很笨拙/危险。

对于这类问题,有没有通用的解决方案?

有两种常见的解决方案。一个是你已经提到的第一个

class A {
  public function doSomething ($outer) { /* code */ }
}

$outer是您的容器。或者将内容对象严格绑定到容器

class A {
  private $outer;
  public function __construct ($outer) {
    $this->outer = $outer;
  }
}

试试这个:

class Container
{
    protected $type;
    protected $contents;
    function __construct($type, Contents $contents)
    {
        $this->type = $type;
        $this->contents = $contents;
        $contents->setContainer($this);
    }
    function display()
    {
        return $this->contents->display();
    }
    public function getType()
    {
        return $this->type;
    }
}
class Contents
{
    /** @var Container */
    protected $container;
    function __construct($stuff)
    {
        $this->stuff = $stuff;
    }
    public function setContainer(Container $container)
    {
        $this->container = $container;
    }
    function display()
    {
        return 'I am '.$this->stuff.' in '.$this->container->getType(); // how to access Container here?
    }
}
$item = new Container('a can', new Contents('Prince Albert'));
echo $item->display()."'n";
// Displays: I am Prince Albert in
// Wanted: I am Prince Albert in a can

作为建议:为每个方法和变量编写公共/受保护/私有,不要使用公共属性。如果你不知道为什么,请阅读这本书:http://www.amazon.com/Objects-Patterns-Practice-Matt-Zandstra/dp/1590599098

使用依赖注入,您将首先构造容器(而不是传入内容):

class Container {
    function __construct($type) {

然后,将容器传递给内容构造函数:

class Contents {
    function __construct($stuff, $container) {

由于引用是相互的,因此您必须在容器上调用 setter:

class Container {
    function setContents($contents)