8.0+ == Именованные аргументы == myFunction(paramName: $value); array_foobar(array: $value); // Использование позиционных аргументов: array_fill(0, 100, 50); // Использование именованных аргументов: array_fill(start_index: 0, count: 100, value: 50); array_fill(value: 50, num: 100, start_index: 0); == Метаатрибуты == Метаатрибуты похожи на интерфейсы, но могут быть опущены, т.е. не инициализированы (имплементированы) вовсе. Метаатрибуты полезны в рефлексии interface ActionHandler { public function execute(); } #[Attribute] class SetUp {} class CopyFile implements ActionHandler { public string $fileName; public string $targetDirectory; #[SetUp] public function fileExists() { if (!file_exists($this->fileName)) { throw new RuntimeException("Файл не найден"); } } #[SetUp] public function targetDirectoryExists() { mkdir($this->targetDirectory); } public function execute() { copy($this->fileName, $this->targetDirectory . '/' . basename($this->fileName)); } } function executeAction(ActionHandler $actionHandler) { $reflection = new ReflectionObject($actionHandler); foreach ($reflection->getMethods() as $method) { $attributes = $method->getAttributes(SetUp::class); if (count($attributes) > 0) { $methodName = $method->getName(); $actionHandler->$methodName(); } } $actionHandler->execute(); } $copyAction = new CopyFile(); $copyAction->fileName = "/tmp/foo.jpg"; $copyAction->targetDirectory = "/home/user"; executeAction($copyAction); == Метаатрибуты могут иметь аргументы == // a.php namespace MyExample; use Attribute; #[Attribute] class MyAttribute { const VALUE = 'value'; private $value; public function __construct($value = null) { $this->value = $value; } } // b.php namespace Another; use MyExampleMyAttribute; #[MyAttribute] #[MyExampleMyAttribute] #[MyAttribute(1234)] #[MyAttribute(value: 1234)] #[MyAttribute(MyAttribute::VALUE)] #[MyAttribute(array("key" => "value"))] #[MyAttribute(100 + 200)] class Thing { } #[MyAttribute(1234), MyAttribute(5678)] class AnotherThing { } == Рефлексия перебором или напрямую == #[Attribute] class MyAttribute { public $value; public function __construct($value) { $this->value = $value; } } #[MyAttribute(value: 1234)] class Thing { } // Перебором function dumpAttributeData($reflection) { $attributes = $reflection->getAttributes(); foreach ($attributes as $attribute) { var_dump($attribute->getName()); var_dump($attribute->getArguments()); var_dump($attribute->newInstance()); } } dumpAttributeData(new ReflectionClass(Thing::class)); /* string(11) "MyAttribute" array(1) { ["value"]=> int(1234) } object(MyAttribute)#3 (1) { ["value"]=> int(1234) } */ // Напрямую function dumpMyAttributeData($reflection) { $attributes = $reflection->getAttributes(MyAttribute::class); foreach ($attributes as $attribute) { var_dump($attribute->getName()); var_dump($attribute->getArguments()); var_dump($attribute->newInstance()); } } dumpAttributeData(new ReflectionClass(Thing::class)); == Атрибутам можно задавать область применения == namespace Example; use Attribute; #[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::IS_REPEATABLE)] class MyAttribute { } == Определение свойств в конструкторе == class Point { public function __construct(protected int $x, protected int $y = 0) { } } == Объединение типов == function foo(int|null $a): bool|int == Строгая типизация == declare(strict_types=1); function sum(int $a, int $b) { return $a + $b; } var_dump(sum(1, 2)); var_dump(sum(1.5, 2.5)); // Выбросит ошибку == Выражение match для сравнения == Аналог switch() с действием $return_value = match (subject_expression) { single_conditional_expression => return_expression, conditional_expression1, conditional_expression2 => return_expression, }; $result = match ($x) { foo() => ..., $this->bar() => ..., // bar() не будет выполнен, если foo() === $x $this->baz => beep(), // beep() будет выполнен только если $x === $this->baz // etc. }; $expressionResult = match ($condition) { 1, 2 => foo(), 3, 4 => bar(), default => baz(), }; $age = 23; $result = match (true) { $age >= 65 => 'пожилой', $age >= 25 => 'взрослый', $age >= 18 => 'совершеннолетний', default => 'ребёнок', }; $condition = 5; try { match ($condition) { 1, 2 => foo(), 3, 4 => bar(), }; } catch (UnhandledMatchError $e) { var_dump($e); } == Выражение "nullsafe" - компактная проверка is_null == $result = $repository?->getUser(5)?->name; == static может быть возвращаемым типом == class Test { public function create(): static { return new static(); } } == throw может быть стрелочной функцией == $fn = fn() => throw new Exception('Исключение в стрелочной функции'); $user = $session->user ?? throw new Exception('Должен быть пользователь');
PHP Справочник v0.05 © 2007-2024 Igor Salnikov aka SunDoctor