Типы PHP
********
.[perex]
[api:Nette\Utils\Type] представляет тип данных PHP. Он служит для анализа, сравнения и работы с типами, полученными как из строки, так и из рефлексии.
Сегодня у PHP очень богатая система типов: от скалярных типов (`int`, `string`) через объекты и интерфейсы до сложных типов (объединение `A|B`, пересечение `A&B` или дизъюнктивная нормальная форма `(A&B)|D`). Кроме того, есть особые типы вроде `void`, `never`, `mixed` и относительные типы `self` и `static`.
Работать с этими типами напрямую, особенно через `ReflectionType`, часто громоздко, потому что приходится рекурсивно различать `ReflectionNamedType`, `ReflectionUnionType` и другие объекты. Класс `Nette\Utils\Type` всё это скрывает и предоставляет **единообразный и интуитивный API** для работы с любым типом, который поддерживает PHP.
Например, он позволяет легко проверить, [принимает ли |#allows()] один тип другой (совместимость), [расширить типы |#with()] или преобразовать рефлексию в читаемую запись.
Установка:
```shell
composer require nette/utils
```
Во всех примерах предполагается, что определён такой псевдоним класса:
```php
use Nette\Utils\Type;
```
fromReflection($reflection): ?Type .[method]
--------------------------------------------
Этот статический метод создаёт объект `Type` на основе рефлексии. Параметром может быть объект `ReflectionMethod` или `ReflectionFunction` (возвращается тип возвращаемого значения) либо объект `ReflectionParameter` или `ReflectionProperty`. Он разрешает `self`, `static` и `parent` в настоящее имя класса. Если у предмета нет типа, возвращает `null`.
```php
class DemoClass
{
public self $foo;
}
$prop = new ReflectionProperty(DemoClass::class, 'foo');
echo Type::fromReflection($prop); // 'DemoClass'
```
fromString(string $type): Type .[method]
----------------------------------------
Этот статический метод создаёт объект `Type` из его строкового представления.
```php
$type = Type::fromString('Foo|Bar');
echo $type; // 'Foo|Bar'
```
fromValue(mixed $value): Type .[method]{data-version:4.0.10}
------------------------------------------------------------
Статический метод, создающий объект Type на основе типа переданного значения.
```php
$type = Type::fromValue('hello'); // 'string'
$type = Type::fromValue(123); // 'int'
$type = Type::fromValue(new stdClass); // 'stdClass'
```
Для ресурсов он возвращает `mixed`, потому что PHP не поддерживает тип `resource`. Для анонимных классов он возвращает имя ближайшего предка или `object`.
```php
$obj = new class extends Foo { };
$type = Type::fromValue($obj); // 'Foo'
```
getNames(): (string|array)[] .[method]
--------------------------------------
Возвращает массив строк, представляющих подтипы, из которых состоит составной тип. Для типов-пересечений возвращает массив массивов.
```php
$type = Type::fromString('string|null'); // или '?string'
$type->getNames(); // ['string', 'null']
$type = Type::fromString('(Foo&Bar)|string');
$type->getNames(); // [['Foo', 'Bar'], 'string']
```
getTypes(): Type[] .[method]
----------------------------
Возвращает массив объектов `Type`, представляющих подтипы, из которых состоит составной тип:
```php
$type = Type::fromString('string|null'); // или '?string'
$type->getTypes(); // [Type::fromString('string'), Type::fromString('null')]
$type = Type::fromString('(Foo&Bar)|string');
$type->getTypes(); // [Type::fromString('Foo&Bar'), Type::fromString('string')]
$type = Type::fromString('Foo&Bar');
$type->getTypes(); // [Type::fromString('Foo'), Type::fromString('Bar')]
```
getSingleName(): ?string .[method]
----------------------------------
Для простых типов (включая простые nullable-типы вроде `?string`) возвращает имя типа. Иначе возвращает null.
```php
$type = Type::fromString('string|null');
echo $type; // '?string'
echo $type->getSingleName(); // 'string'
$type = Type::fromString('?Foo');
echo $type; // '?Foo'
echo $type->getSingleName(); // 'Foo'
$type = Type::fromString('Foo|Bar');
echo $type; // 'Foo|Bar'
echo $type->getSingleName(); // null (это тип-объединение)
```
isSimple(): bool .[method]
--------------------------
Возвращает, является ли тип простым. К простым типам относятся и простые nullable-типы (например, `?string`, `?Foo`):
```php
$type = Type::fromString('string');
$type->isSimple(); // true
$type->isUnion(); // false
$type = Type::fromString('?Foo'); // или 'Foo|null'
$type->isSimple(); // true
$type->isUnion(); // true (потому что содержит null)
```
isUnion(): bool .[method]
-------------------------
Возвращает, является ли тип объединением (содержит `|`).
```php
$type = Type::fromString('Foo&Bar');
$type->isUnion(); // true
```
isIntersection(): bool .[method]
--------------------------------
Возвращает, является ли тип пересечением (содержит `&`).
```php
$type = Type::fromString('Foo&Bar');
$type->isIntersection(); // true
```
isBuiltin(): bool .[method]
---------------------------
Возвращает, является ли тип простым и при этом встроенным типом PHP (таким как `string`, `int`, `array`, `callable` и так далее).
```php
$type = Type::fromString('string');
$type->isBuiltin(); // true
$type = Type::fromString('string|int');
$type->isBuiltin(); // false
$type = Type::fromString('Foo');
$type->isBuiltin(); // false
```
isClass(): bool .[method]
-------------------------
Возвращает, является ли тип простым и при этом именем класса (а не встроенным типом вроде `string` или `int`).
```php
$type = Type::fromString('string');
$type->isClass(); // false
$type = Type::fromString('Foo|null');
$type->isClass(); // true
$type = Type::fromString('Foo|Bar');
$type->isClass(); // false
```
isClassKeyword(): bool .[method]
--------------------------------
Возвращает, является ли тип одним из внутренних ключевых слов `self`, `parent` или `static`.
```php
$type = Type::fromString('self');
$type->isClassKeyword(); // true
$type = Type::fromString('Foo');
$type->isClassKeyword(); // false
```
allows(string|Type $type): bool .[method]
-----------------------------------------
Метод `allows()` проверяет совместимость типов. Например, он может определить, можно ли передать значение определённого типа как параметр функции, ожидающей этот тип.
```php
$type = Type::fromString('string|null');
$type->allows('string'); // true
$type->allows('null'); // true
$type->allows('Foo'); // false
$type = Type::fromString('mixed');
$type->allows('null'); // true
```
with(string|Type $type): Type .[method]{data-version:4.0.10}
------------------------------------------------------------
Возвращает объект Type, принимающий и исходный тип, и добавляемый. Тем самым создаётся так называемый тип-объединение.
Метод устроен разумно и не дублирует типы без нужды. Если вы добавите тип, который уже есть или является надмножеством текущего (например, добавите `mixed` к `string`), результат упростится.
```php
$type = Type::fromString('string');
// Расширяем до nullable string
echo $type->with('null'); // '?string'
// Создаём тип-объединение
echo $type->with('int'); // 'string|int'
// Добавляем тип, который перекрывает всё
echo $type->with('mixed'); // 'mixed'
```
Типы PHP
Nette\Utils\Type представляет
тип данных PHP. Он служит для анализа, сравнения и работы с типами,
полученными как из строки, так и из рефлексии.
Сегодня у PHP очень богатая система типов: от скалярных типов
(int, string) через объекты и интерфейсы до сложных типов
(объединение A|B, пересечение A&B или дизъюнктивная
нормальная форма (A&B)|D). Кроме того, есть особые типы вроде
void, never, mixed и относительные типы self и
static.
Работать с этими типами напрямую, особенно через ReflectionType,
часто громоздко, потому что приходится рекурсивно различать
ReflectionNamedType, ReflectionUnionType и другие объекты. Класс
Nette\Utils\Type всё это скрывает и предоставляет единообразный и
интуитивный API для работы с любым типом, который поддерживает PHP.
Например, он позволяет легко проверить, принимает ли
один тип другой (совместимость), расширить типы или
преобразовать рефлексию в читаемую запись.
Установка:
composer require nette/utils
Во всех примерах предполагается, что определён такой псевдоним
класса:
use Nette\Utils\Type;
fromReflection ($reflection): ?Type
Этот статический метод создаёт объект Type на основе рефлексии.
Параметром может быть объект ReflectionMethod или ReflectionFunction
(возвращается тип возвращаемого значения) либо объект
ReflectionParameter или ReflectionProperty. Он разрешает self,
static и parent в настоящее имя класса. Если у предмета нет
типа, возвращает null.
class DemoClass
{
public self $foo;
}
$prop = new ReflectionProperty(DemoClass::class, 'foo');
echo Type::fromReflection($prop); // 'DemoClass'
fromString (string $type): Type
Этот статический метод создаёт объект Type из его строкового
представления.
$type = Type::fromString('Foo|Bar');
echo $type; // 'Foo|Bar'
fromValue (mixed
$value): Type
Статический метод, создающий объект Type на основе типа переданного
значения.
$type = Type::fromValue('hello'); // 'string'
$type = Type::fromValue(123); // 'int'
$type = Type::fromValue(new stdClass); // 'stdClass'
Для ресурсов он возвращает mixed, потому что PHP не поддерживает
тип resource. Для анонимных классов он возвращает имя ближайшего
предка или object.
$obj = new class extends Foo { };
$type = Type::fromValue($obj); // 'Foo'
getNames ():
(string|array)[]
Возвращает массив строк, представляющих подтипы, из которых состоит
составной тип. Для типов-пересечений возвращает массив массивов.
$type = Type::fromString('string|null'); // или '?string'
$type->getNames(); // ['string', 'null']
$type = Type::fromString('(Foo&Bar)|string');
$type->getNames(); // [['Foo', 'Bar'], 'string']
getTypes(): Type[]
Возвращает массив объектов Type, представляющих подтипы, из
которых состоит составной тип:
$type = Type::fromString('string|null'); // или '?string'
$type->getTypes(); // [Type::fromString('string'), Type::fromString('null')]
$type = Type::fromString('(Foo&Bar)|string');
$type->getTypes(); // [Type::fromString('Foo&Bar'), Type::fromString('string')]
$type = Type::fromString('Foo&Bar');
$type->getTypes(); // [Type::fromString('Foo'), Type::fromString('Bar')]
getSingleName(): ?string
Для простых типов (включая простые nullable-типы вроде ?string)
возвращает имя типа. Иначе возвращает null.
$type = Type::fromString('string|null');
echo $type; // '?string'
echo $type->getSingleName(); // 'string'
$type = Type::fromString('?Foo');
echo $type; // '?Foo'
echo $type->getSingleName(); // 'Foo'
$type = Type::fromString('Foo|Bar');
echo $type; // 'Foo|Bar'
echo $type->getSingleName(); // null (это тип-объединение)
isSimple(): bool
Возвращает, является ли тип простым. К простым типам относятся и
простые nullable-типы (например, ?string, ?Foo):
$type = Type::fromString('string');
$type->isSimple(); // true
$type->isUnion(); // false
$type = Type::fromString('?Foo'); // или 'Foo|null'
$type->isSimple(); // true
$type->isUnion(); // true (потому что содержит null)
isUnion(): bool
Возвращает, является ли тип объединением (содержит |).
$type = Type::fromString('Foo&Bar');
$type->isUnion(); // true
isIntersection(): bool
Возвращает, является ли тип пересечением (содержит &).
$type = Type::fromString('Foo&Bar');
$type->isIntersection(); // true
isBuiltin(): bool
Возвращает, является ли тип простым и при этом встроенным типом PHP
(таким как string, int, array, callable и так далее).
$type = Type::fromString('string');
$type->isBuiltin(); // true
$type = Type::fromString('string|int');
$type->isBuiltin(); // false
$type = Type::fromString('Foo');
$type->isBuiltin(); // false
isClass(): bool
Возвращает, является ли тип простым и при этом именем класса (а не
встроенным типом вроде string или int).
$type = Type::fromString('string');
$type->isClass(); // false
$type = Type::fromString('Foo|null');
$type->isClass(); // true
$type = Type::fromString('Foo|Bar');
$type->isClass(); // false
isClassKeyword(): bool
Возвращает, является ли тип одним из внутренних ключевых слов
self, parent или static.
$type = Type::fromString('self');
$type->isClassKeyword(); // true
$type = Type::fromString('Foo');
$type->isClassKeyword(); // false
allows (string|Type $type): bool
Метод allows() проверяет совместимость типов. Например, он может
определить, можно ли передать значение определённого типа как
параметр функции, ожидающей этот тип.
$type = Type::fromString('string|null');
$type->allows('string'); // true
$type->allows('null'); // true
$type->allows('Foo'); // false
$type = Type::fromString('mixed');
$type->allows('null'); // true
with (string|Type
$type): Type
Возвращает объект Type, принимающий и исходный тип, и добавляемый. Тем
самым создаётся так называемый тип-объединение.
Метод устроен разумно и не дублирует типы без нужды. Если вы добавите
тип, который уже есть или является надмножеством текущего (например,
добавите mixed к string), результат упростится.
$type = Type::fromString('string');
// Расширяем до nullable string
echo $type->with('null'); // '?string'
// Создаём тип-объединение
echo $type->with('int'); // 'string|int'
// Добавляем тип, который перекрывает всё
echo $type->with('mixed'); // 'mixed'