3v4l.org

run code in 300+ PHP versions simultaneously
<?php #[Attribute] class Getter{} #[Attribute] class Setter{} class SetterGetterException extends Exception{} trait SetterGetter { private function getFieldNameFromMethodName(string $methodName): string { $fieldName = mb_substr($methodName, 3); $fieldNameFirstChar = mb_strtolower(mb_substr($fieldName, 0, 1)); $fieldNameLastChars = mb_substr($fieldName, 1); $fieldName = $fieldNameFirstChar . $fieldNameLastChars; return $fieldName; } private function methodAllowedToBeUsedOnProperty(string $methodName, object $object, string $fieldName): array { $methods = []; $property = new ReflectionProperty(get_class($object), $fieldName); $properties = $property->getAttributes(); foreach ($properties as $property) { $methodName = $property->getName(); if ($methodName === 'Setter') { $methods[] = 'set'; } elseif ($methodName === 'Getter') { $methods[] = 'get'; } } return $methods; } public function __call(string $name, array $arguments) { $prefix = mb_substr($name, 0, 3); if ($prefix !== 'get' && $prefix !== 'set') { throw new SetterGetterException('Из необъявленных методов этого класса можно вызывать только геттер и сеттер.'); } $fieldName = $this->getFieldNameFromMethodName($name); if (!property_exists(get_class($this), $fieldName)) { throw new SetterGetterException('В классе ' . get_class($object) . 'не существует свойства с именем' . $fieldName); } $methods = $this->methodAllowedToBeUsedOnProperty($name, $this, $fieldName); if (!in_array($prefix, $methods)) { throw new SetterGetterException('К этому полю нельзя обращаться через метод ' . $prefix); } if ($prefix === 'get') { return $this->$fieldName; } elseif ($prefix === 'set') { if (count($arguments) !== 1) { throw new SetterGetterException('В сеттер можно передавать только один аргумент.'); } $fieldValue = $arguments[0]; $this->$fieldName = $fieldValue; } } } class Test { use SetterGetter; #[Setter] #[Getter] private int $number; } $test = new Test(); $test->setNumber(5); echo $test->getNumber();
Output for 8.1.0 - 8.1.28, 8.2.0 - 8.2.19, 8.3.0 - 8.3.7
5

preferences:
86.41 ms | 402 KiB | 62 Q