<?phpnamespaceDesignPatterns\Structural\Composite;/** * The composite node MUST extend the component contract. This is mandatory for building * a tree of components. */classFormimplementsRenderableInterface{/** * @var RenderableInterface[] */private$elements;/** * runs through all elements and calls render() on them, then returns the complete representation * of the form. * * from the outside, one will not see this and the form will act like a single object instance * * @return string */publicfunctionrender():string{$formCode='<form>';foreach($this->elementsas$element){$formCode.=$element->render();}$formCode.='</form>';return$formCode;}/** * @param RenderableInterface $element */publicfunctionaddElement(RenderableInterface$element){$this->elements[]=$element;}}

<?phpnamespaceDesignPatterns\Structural\Composite\Tests;useDesignPatterns\Structural\Composite;usePHPUnit\Framework\TestCase;classCompositeTestextendsTestCase{publicfunctiontestRender(){$form=newComposite\Form();$form->addElement(newComposite\TextElement('Email:'));$form->addElement(newComposite\InputElement());$embed=newComposite\Form();$embed->addElement(newComposite\TextElement('Password:'));$embed->addElement(newComposite\InputElement());$form->addElement($embed);// This is just an example, in a real world scenario it is important to remember that web browsers do not// currently support nested forms$this->assertEquals('<form>Email:<input type="text" /><form>Password:<input type="text" /></form></form>',$form->render());}}