2

I'm struggling to find a correct approach to pass data between classes, which do not directly call each other, and are only related through a parent class (which I now use, but I consider it a dirty workaround rather than anything near a solution).

I have 3 classes both able to read input and write output, and based on configuration I set one to read, another one to write. It may even be the same class, they all share a parent class, but they are always two separate instances called from a controller class.

Currently I use this sort of functionality:

class daddy {
    public static $data;
}

class son extends daddy {
    public function setData() {
        parent::$data = "candy";
    }
}

class daughter extends daddy {
    public function getData() {
        echo parent::$data;
    }
}

while($processALineFromConfig)
    $son = new son;
    $son->setData();

    $daughter = new daughter;
    $daughter->getData();
    daddy::$data = null; //reset the data, in the actual code $daughter does that in parent::
}

Instantination of these classes runs in a loop, therefore I always need to reset the data after $daughter receives them, 'cos otherwise it would stay there for another pass through the loop.

I'm absolutely sure it's not how class inheritance is supposed to be used, however I'm struggling to find a real solution. It only makes sense the data should be stored in the controller which calls these classes, not the parent, but I already use return values in the setter and getter functions, and I am not passing a variable by reference to store it there to these functions 'cos I have optional parameters there and I'm trying to keep the code clean.

What would be the correct approach to pass data through the controller then?

Thanks!

1 Answer 1

1

The best option would be for two object share some other, third object. This would be the class for "third object" which will ensure the exchage:

class Messenger
{
    private $data;

    public function store($value)
    {
        $this->data = $value;
    }

    public function fetch()
    {
        return $this->data;
    }
}

Then a class for both instance, that will need to share some state:

class FooBar
{

    private $messenger;
    private $name = 'Nobody';

    public function __construct($messenger, $name)
    {
        $this->messenger = messenger;
        $this->name = $name;
    }

    public function setSharedParam($value)
    {
        $this->messenger->store($value);
    }

    public function getSharedParameter()
    {
        return $this->name . ': ' . $this->messenger->fetch();
    }
}

You utilize the classes like this:

$conduit = new Messenger;

$john = new FooBar($conduit, 'Crichton');
$dominar = new FooBar($conduit, 'Rygel');

$dominar->setSharedParameter('crackers');
echo $john->getSharedParameter();
// Crichton: crackers

Basically, they both are accessing the same object. This also can be further expanded by making both instance to observe the instance of Messenger.

Sign up to request clarification or add additional context in comments.

4 Comments

The Principle of least astonishment (POLS) : If you write to a class property, then a method should be named setFoo() and an assignment must only be done. If you return a property, then it a method should be named as getFoo(). This is what expected. What you're doing in Messenger obviously breaks the POLS.
So, are you implying that you where astonished by the complexity of this EXAMPLE ?
POLS possibly applies to Messenger with the $data property, but for example sake, I don't think it applies to FooBar. The set and get method names merely help further explain the logic.
@DaveJust The names were chosen to emphasize, that the shared DAO (which this basically is an extremely simplified version of) and objects, which consume it, are not required to have identical/similar API. The OP was trying to implement this by extending classes and depending on global state. I felt that enforcing a clear-cut separation was far more valuable then some imagined PoLS violation because of your personal naming preconceptions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.