3v4l.org

run code in 300+ PHP versions simultaneously
<?php abstract class FormModel { private array $attributes; private array $attributesLabels; private array $attributesErrors = []; public function __construct() { $this->attributes = $this->attributes(); $this->attributesLabels = $this->attributeLabels(); } public function getAttributeValue(string $attribute) { return $this->readProperty($attribute); } public function attributeHint(string $attribute): string { $hints = $this->attributeHints(); return $hints[$attribute] ?? ''; } public function attributeHints(): array { return []; } public function attributeLabel(string $attribute): string { return $this->attributesLabels[$attribute] ?? $this->generateAttributeLabel($attribute); } public function formName(): string { return ''; } public function hasAttribute(string $attribute): bool { return \array_key_exists($attribute, $this->attributes); } public function error(string $attribute): array { return $this->attributesErrors[$attribute] ?? []; } public function errors(): array { return $this->attributesErrors ?? []; } public function errorSummary(bool $showAllErrors): array { $lines = []; $errors = $showAllErrors ? $this->errors() : [$this->firstErrors()]; foreach ($errors as $error) { $lines = \array_merge($lines, $error); } return $lines; } public function firstError(string $attribute): string { return isset($this->attributesErrors[$attribute]) ? reset($this->attributesErrors[$attribute]) : ''; } public function firstErrors(): array { if (empty($this->attributesErrors)) { return []; } $errors = []; foreach ($this->attributesErrors as $name => $es) { if (!empty($es)) { $errors[$name] = \reset($es); } } return $errors; } public function hasErrors(?string $attribute = null): bool { return $attribute === null ? !empty($this->attributesErrors) : isset($this->attributesErrors[$attribute]); } public function load(array $data): bool { $result = false; $scope = $this->formName(); if ($scope === '' && !empty($data)) { $this->setAttributes($data); $result = true; } elseif (isset($data[$scope])) { $this->setAttributes($data[$scope]); $result = true; } return $result; } public function setAttributes(array $values): void { foreach ($values as $name => $value) { if (isset($this->attributes[$name])) { switch ($this->attributes[$name]) { case 'bool': $this->writeProperty($name, (bool) $value); break; case 'float': $this->writeProperty($name, (float) $value); break; case 'int': $this->writeProperty($name, (int) $value); break; default: $this->writeProperty($name, $value); break; } } } } protected function addError(string $attribute, string $error): void { $this->attributesErrors[$attribute][] = $error; } private function addErrors(array $items): void { foreach ($items as $attribute => $errors) { foreach ((array)$errors as $error) { $this->attributesErrors[$attribute][] = $error; } } } private function attributes(): array { $class = new \ReflectionClass($this); foreach ($class->getProperties() as $property) { if (!$property->isStatic()) { $type = (new \ReflectionProperty($property->class, $property->name))->getType(); if ($type !== null) { $this->attributes[$property->getName()] = $type->getName(); } else { throw new \InvalidArgumentException( "You must specify the type hint for \"$property->class\" class." ); } } } return $this->attributes; } private function clearErrors(?string $attribute = null): void { if ($attribute === null) { $this->attributesErrors = []; } else { unset($this->attributesErrors[$attribute]); } } private function readProperty(string $attribute) { $class = get_class($this); if (!property_exists($class, $attribute)) { throw new InvalidArgumentException("Undefined property: \"$class::$attribute\"."); } $getter = fn ($class, $attribute) => $class->$attribute; $getter = \Closure::bind($getter, null, $this); return $getter($this, $attribute); } private function writeProperty(string $attribute, $value): void { $setter = fn ($class, $attribute, $value) => $class->$attribute = $value; $setter = \Closure::bind($setter, null, $this); $setter($this, $attribute, $value); } } class LoginForm extends FormModel { private ?string $login = null; private ?string $password = null; private bool $rememberMe = false; public function getLogin(): ?string { return $this->login; } public function getPassword(): ?string { return $this->password; } public function getRememberMe(): bool { return $this->rememberMe; } public function login(string $value): void { $this->login = $value; } public function password(string $value): void { $this->password = $value; } public function rememberMe(bool $value): void { $this->rememberMe = $value; } public function attributeHints(): array { return [ 'login' => 'Write your id or email.', 'password' => 'Write your password.' ]; } public function attributeLabels(): array { return [ 'login' => 'Login:', 'password' => 'Password:', 'rememberMe' => 'remember Me:' ]; } public function formName(): string { return 'LoginForm'; } public function addError(string $attribute, string $error): void { parent::addError($attribute, $error); } } $form = new LoginForm(); $form->login('yiiliveext'); $form->addError('login', 'Login incorrect'); var_dump($form->errors());
Output for 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.33, 8.2.0 - 8.2.29, 8.3.0 - 8.3.25, 8.4.1 - 8.4.12
array(1) { ["login"]=> array(1) { [0]=> string(15) "Login incorrect" } }
Output for 7.2.0 - 7.2.33, 7.3.0 - 7.3.33
Parse error: syntax error, unexpected 'array' (T_ARRAY), expecting function (T_FUNCTION) or const (T_CONST) in /in/CWjDe on line 4
Process exited with code 255.

preferences:
139.36 ms | 407 KiB | 5 Q