<?php
class Input
{
public function __construct(
private readonly string $type,
private readonly string $name,
private readonly string $defaultValue = '',
private readonly array $parameters = [],
) {
}
public function render(): string
{
$attributes = [
'type' => $this->type,
'name' => $this->name,
'id' => $this->name,
'value' => $this->defaultValue,
...$this->parameters,
];
return sprintf('<input %s>', $this->renderHtmlAttributes($attributes));
}
protected function renderHtmlAttributes(array $attributes): string
{
$htmlAttributes = [];
foreach ($attributes as $key => $value) {
$htmlAttributes[] = sprintf('%s="%s"', $key, $value);
}
return implode(' ', $htmlAttributes);
}
}
class InputSelect extends Input
{
public function __construct(
private readonly string $name,
private readonly array $options,
private readonly string $defaultValue = '',
private readonly array $parameters = [],
) {
parent::__construct('select', $name, $defaultValue, $parameters);
}
public function render(): string
{
$options = [];
foreach ($this->options as $value => $label) {
$selected = $value === $this->defaultValue ? 'selected' : '';
$options[] = sprintf('<option value="%s" %s>%s</option>', $value, $selected, $label);
}
$options = implode('', $options);
$attributes = [
'name' => $this->name,
'id' => $this->name,
...$this->parameters,
];
return sprintf('<select %s>%s</select>', $this->renderHtmlAttributes($attributes), $options);
}
}
class Label
{
public function __construct(
private readonly string $label,
private readonly string $for,
private readonly Input $input,
private readonly string $position = 'before',
) {
}
public function render(): string
{
if ($this->position === 'before') {
$label = sprintf('<label for="%s">%s</label>', $this->for, $this->label);
return $label . $this->input->render();
}
if ($this->position === 'after') {
$label = sprintf('<label for="%s">%s</label>', $this->for, $this->label);
return $this->input->render() . $label;
}
// Input inner label
$inputRender = $this->input->render();
return "<label for='{$this->for}'>{$this->label}{$inputRender}</label>";
}
}
class FormBuilder
{
public static function createInput(string $type, string $name, string $defaultValue = '', array $parameters = []): Input
{
return new Input($type, $name, $defaultValue, $parameters);
}
public static function createInputSelect(string $name, array $options, string $defaultValue = '', array $parameters = []): InputSelect
{
return new InputSelect($name, $options, $defaultValue, $parameters);
}
public static function createLabel(string $label, string $for, Input $input, string $position = 'before'): Label
{
return new Label($label, $for, $input, $position);
}
}
echo FormBuilder::createLabel('Name', 'name', FormBuilder::createInput('text', 'name'))->render();