Mr. Lance E Sloan
Mr. Lance E Sloan

Reputation: 3387

how to access containing object's properties in PHP?

I'm writing some PHP code in which one object (a "Container") keeps a pointer to another object (the "Contents"). The problem is that the contents needs to access methods or properties of the container.

Here's a simplified example of what I want to do:

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

What's the right way to do this?

I've tried a couple of methods that work, but they feel wrong. For example:

Is there a common solution for this kind of problem?

Upvotes: 4

Views: 1132

Answers (3)

user680786
user680786

Reputation:

Try this:

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

And as advice: write public/protected/private for each method and variables, don't use public properties. If you don't know why, read this book: http://www.amazon.com/Objects-Patterns-Practice-Matt-Zandstra/dp/1590599098

Upvotes: 1

KingCrunch
KingCrunch

Reputation: 131841

At all there are two common solution. The one is the first one you already mention

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

where $outer is your container. Or you strictly bind the content objects to the container

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

Upvotes: 4

Matthew Flaschen
Matthew Flaschen

Reputation: 284786

With dependency injection, you would construct the Container first (not passing in a Contents):

class Container {
    function __construct($type) {

Then, you would pass the Container to the Contents constructor:

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

Since the reference is mutual, you would have to call a setter on container:

class Container {
    function setContents($contents)

Upvotes: 1

Related Questions