It depends a bit what you want. As your types are just property objects I think the solution by Vahe Shadunts is most lightweight and easy.
If you want to get more control in PHP you need to make use of getters and setters. This will allow you to make it work more specific.
As far as foreach
Docs is concerned, all your children object needs to do is to implement the Iterator
or IteratorAggregate
interface and it then can be used inside foreach
(see Object IterationDocs).
Here is an example:
$jane = ConcretePerson::build('Jane', 'Lovelock');
$janesChildren = $jane->getChildren();
$janesChildren->attachPerson(ConcretePerson::build('Clara'));
$janesChildren->attachPerson(ConcretePerson::build('Alexis'));
$janesChildren->attachPerson(ConcretePerson::build('Peter'));
$janesChildren->attachPerson(ConcretePerson::build('Shanti'));
printf(
"%s %s has the following children (%d):\n",
$jane->getFirstname(),
$jane->getLastname(),
count($jane->getChildren())
);
foreach($janesChildren as $oneOfJanesChildren)
{
echo ' - ', $oneOfJanesChildren->getFirstname(), "\n";
}
The output:
Jane Lovelock has the following children (4):
- Clara
- Alexis
- Peter
- Shanti
These named interfaces and objects that work in the background here (I link the code at the end) have certain benefits compared with just arrays and properties if you need more functionality (e.g. over time).
Let's say Jane is married with Janet so they both share the same children so both share them:
$janet = ConcretePerson::build('Janet', 'Peach');
$janet->setChildren($janesChildren);
Now Janet gets a new child:
$janet->getChildren()->attachPerson(ConcretePerson::build('Feli'));
And so does automatically Jane because both share the same children object.
However PHP is not strong with these typed-collections therefore you have quite some boilerplate code to get this done.
code gist