Example 1

Use case: Create a form composition - labels. textfield and label

<?php

interface FormElement
{
    public function render(): string;
}

interface FormGroup
{
    public function addElement(FormElement $formElement): void;
}
<?php

class Label implements FormElement
{
    /**
     * @var string
     */
    private $name;

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

    public function render(): string
    {
        return "<label>$this->name</label>";
    }
}

class TextField implements FormElement
{
    public function render(): string
    {
        return '<input type="text" />';
    }
}
<?php

trait Groupable
{
    private $elements = [];

    public function addElement(FormElement $formElement): void
    {
        $this->elements[] = $formElement;
    }

    private function renderGroup()
    {
        $form = '';
        foreach ( $this->elements as $element ) {
            /** @var FormElement $element */
            $form .= $element->render() . PHP_EOL;
        }

        return $form;
    }
}

 

<?php

class FieldSet implements FormElement, FormGroup
{
    use Groupable;
    /**
     * @var string
     */
    private $title;

    public function __construct(string $title)
    {
        $this->title = $title;
    }

    public function render(): string
    {
        $form = '<fieldset>' . PHP_EOL;
        $form .= "<h3>$this->title</h3>" . PHP_EOL;
        $form .= $this->renderGroup();
        $form .= '</fieldset>' . PHP_EOL;

        return $form;
    }
}
<?php

class Form implements FormElement, FormGroup
{
    use Groupable;

    public function render(): string
    {
        $form = '<form>' . PHP_EOL;
        $form .= $this->renderGroup();
        $form .= '</form>' . PHP_EOL;

        return $form;
    }
}

Client code:

<?php

$form = new Form();

$label = new Label('Name');
$textName = new TextField();
$form->addElement($label);
$form->addElement($textName);


$fieldset = new FieldSet('User Data');

$label = new Label('Weight');
$textName = new TextField();
$fieldset->addElement($label);
$fieldset->addElement($textName);

$label = new Label('Height');
$textName = new TextField();
$fieldset->addElexment($label);
$fieldset->addElement($textName);


$form->addElement($fieldset);

echo $form->render();

// Output
<form>
    <label>Name</label>
    <input type="text" />
    <fieldset>
        <h3>User Data</h3>
        <label>Weight</label>
        <input type="text" />
        <label>Height</label>
        <input type="text" />
    </fieldset>
</form>