Php перечисляемые типы данных

Php перечисляемые типы данных

Перечисления — это ограничивающий слой над классами и константами классов, предназначенный для предоставления способа определения закрытого набора возможных значений для типа.

enum Suit
case Hearts ;
case Diamonds ;
case Clubs ;
case Spades ;
>

Полное описание смотрите в главе о перечислениях.

Casting

Если перечисление ( enum ) преобразуется в объект ( object ), оно не изменяется. Если перечисление ( enum ) преобразуется в массив ( array ), то создаётся массив с одним ключом name (для простых перечислений) или массив с двумя ключами name и value (для типизированных перечислений). Все остальные приведения типов приведут к ошибке.

User Contributed Notes 1 note

/**
* This is a sample
* How to use Enum to create a custom exception cases
* PHP 8.1^
*/

enum MyExceptionCase case InvalidMethod ;
case InvalidProperty ;
case Timeout ;
>

class MyException extends Exception function __construct (private MyExceptionCase $case ) match ( $case ) MyExceptionCase :: InvalidMethod => parent :: __construct ( «Bad Request — Invalid Method» , 400 ),
MyExceptionCase :: InvalidProperty => parent :: __construct ( «Bad Request — Invalid Property» , 400 ),
MyExceptionCase :: Timeout => parent :: __construct ( «Bad Request — Timeout» , 400 )
>;
>
>

// Testing my custom exception class
try throw new MyException ( MyExceptionCase :: InvalidMethod );
> catch ( MyException $myE ) echo $myE -> getMessage (); // Bad Request — Invalid Method
>

Источник

PHP 8.1: Enums (Перечисления)

PHP 8.1: Enums (Перечисления)

Вот и подошли вкусности, Enums точно появятся!

Встроенная поддержка перечислений будет добавлена ​​в PHP 8.1. Кто-то считает, что перечисления не нужны, а если совсем уж приспичило, то можно воспользоваться сторонними пакетами, как например Spatie/Enum , ну а кто-то, в том числе и я, считает, что PHP не хватает нативного функционала по Enums. И я рад, что контрибьютерам PHP удалось наконец-то воплотить это в реальность.

Итак, Enumeration или для краткости Enum — это перечислимый тип, который имеет фиксированное количество возможных значений.

Например, масти в колоде игральных карт. В колоде есть четыре масти, и они фиксированы: трефы , бубны , черви и пики. В PHP эти масти можно перечислить с помощью Enum:

enum Suit case Clubs; 
case Diamonds;
case Hearts;
case Spades;
>

С Suit Enum теперь возможно принудительно применять типы при принятии или возврате значения масти:

function pick_card(Suit $suit) <>
pick_card(Suit::Clubs); 
pick_card(Suit::Diamonds);
pick_card(Suit::Hearts);
pick_card(Suit::Spades);

Или пример использования, что чаще всего мне как раз и приходиться использовать, статусы заказа в интернет-магазине:

enum Status 
case CREATED;
case COMPLETED;
case CANCELED;
>

Теперь в модели заказа Order мы можем использовать статусы следующим образом:

class Order 
public function __construct(
public Status $status,
) <>
>
$post = new Order(Status::CREATED);

В отличие от внутреннего использования специальных строк или чисел для хранения и работы с параметрами, перечисления делают код приложения более читабельным и позволяют избежать неожиданного состояния приложения.

Читайте также:  Class and objects in python

Enum синтаксис

PHP 8.1 резервирует и использует ключевое слово enum для объявления Enums. Синтаксис аналогичен синтаксису трейта/класса/интерфейса:

enum Status 
case CREATED;
case COMPLETED;
case CANCELED;
case REFUNDED;
case FAILED;
>

Чувствительность к регистру

Само имя Enum нечувствительно к регистру , и оно соответствует тому, как PHP обрабатывает классы и функции без учета регистра. Отдельные регистры в Enum нечувствительны к регистру.

enum Status 
case created;
case Completed;
case canCeleD;
>

Enum методы

Перечисления могут содержать методы, как и классы. Это очень мощная функция, особенно в сочетании с оператором match :

enum Status 
case CREATED;
case COMPLETED;
case CANCELED;

public function color(): string
return match($this)
Status::CREATED => 'grey',
Status::COMPLETED => 'green',
Status::CANCELED => 'red'
>;
>
>

и далее использовать в коде как:

$status = Status::COMPLETED; 
$status->color(); // "green"

Разрешено использовать статические методы. Также обратите внимание, что вы можете использовать в перечислении self :

enum Status 
// …

public function color(): string
return match($this)
self::CREATED => 'grey',
self::COMPLETED => 'green',
self::CANCELED=> 'red',
>;
>
>

Перечисления могут реализовывать интерфейсы, как и обычные классы:

interface HasColor 
public function color(): string;
>
enum Status implements HasColor 
case CREATED;
case COMPLETED;
case CANCELED;

public function color(): string < /* … */ >
>

Перечисления не должны содержать свойств

Одно из наиболее важных различий между Enum и классом заключается в том, что Enums не могут иметь никакого состояния. Объявление или установка свойств не разрешены. Статические свойства также не допускаются.

enum Foo private string $test; 
private static string $test2;
>

// Fatal error: Enums may not include member variables in . on line .

Кроме того, не допускается динамическая установка свойств:

enum Foo case Bar; 
>
$bar = Foo::Bar;
$bar->test = 42;

// Error: Enum properties are immutable in .

Enum значения или «Поддерживаемые перечисления»

Изначально значения Enum представлены внутри объектами, но вы можете присвоить им какое-то значение, например для сериализации их в базу данных.

enum Status: string 
case CREATED = 'created';
case COMPLETED = 'completed';
case CANCELED = 'canceled';
>

Обратите внимание на объявление типа в определении перечисления. Он указывает, что все значения перечисления имеют данный тип. Вы также можете сделать их целочисленными — int. Обратите внимание, что разрешены только типы int и string, как значения перечисления.

enum Status: int 
case CREATED = 1;
case COMPLETED = 2;
case CANCELED = 3;
>

Технический термин для такого ввода перечислений называется «поддерживаемые перечисления», поскольку они «подкреплены» более простым значением. Если вы решили присвоить значения перечисления, тогда все варианты должны иметь какое-то значение. Вы не можете смешивать и сочетать их. Перечисления без «поддержки» называются «чистыми перечислениями».

Сериализация поддерживаемых перечислений

Если вы присвоите значения enum, вам вероятно понадобится способ их сериализации и десериализации. Их сериализация означает, что вам нужен способ доступа к значению перечисления. Это делается с помощью public свойства value, обратите внимание, что оно только для чтения:

$value = Status::CANCELED->value; // 3

Получить перечисление из значения можно с помощью Enum::from

$status = Status::from(2); // Status::COMPLETED

Также можно использовать tryFrom для возврата null при неизвестном значении. Если бы вы использовали from, то возникло бы исключение.

$status = Status::from('unknown'); // ValueError 
$status = Status::tryFrom('unknown'); // null

Вы также можете использовать встроенные функции serialize и unserialize на перечислениях. Кроме того, вы можете использовать json_serialize в сочетании с поддерживаемыми перечислениями, ее результатом будет значение перечисления. Это поведение можно изменить, реализовав JsonSerializable.

Читайте также:  Просмотр массива $GLOBALS

Список значений перечисления

Вы можете использовать статический метод cases() , чтобы получить список всех доступных «случаев» в перечислении: Enum::cases()

Status::cases(); 

// [Status::CREATED, Status::COMPLETED, Status::CANCELED]

Перечисления — это объекты

Как уже выше упоминалось, значения перечислений представлены как объекты, хотя на самом деле это одноэлементные объекты. Это означает, что вы можете сравнивать их так:

$statusA = Status::COMPLETED; 
$statusB = Status::COMPLETED;
$statusC = Status::CANCELED;

$statusA === $statusB; // true
$statusA === $statusC; // false
$statusC instanceof Status; // true

Перечисления как ключи массива

Поскольку значения перечислений на самом деле являются объектами, в настоящее время их невозможно использовать в качестве ключей массива. Следующий код приведет к ошибке:

$list = [ 
Status::CREATED => 'created',
// …
];

Существует RFC для изменения этого поведения, но он еще не был принят.

Это означает, что вы можете использовать только перечисления в качестве ключей в SplObjectStorage и WeakMaps.

Перечисления могут иметь ноль или более значений

Внутри структуры enum может содержаться любое количество case от нуля до бесконечности. Оба этих объявления Enum валидны:

enum HTTPMethods case GET; 
case POST;
>

Создание экземпляров с помощью new запрещено

Хотя кеймы Enum сами по себе являются объектами, их нельзя создавать с помощью конструкции new. Обе следующие new конструкции не допускаются:

enum Foo case Bar; 
>

new Foo(); // Fatal error: Uncaught Error: Cannot instantiate enum Foo
new Foo::Bar(); Parse error: syntax error, unexpected identifier "Bar", expecting variable or "$"

Перечисления не могут быть расширены и не должны наследовать

Перечисления объявляются как final, и Enum не может наследоваться от другого Enum или класса.

enum Foo extends Bar <> 

// Parse error: syntax error, unexpected token "extends", expecting "
enum Foo <> 
class Bar extends Foo <>

// Fatal error: Class Bar may not inherit from final class (Foo) in . on line .

Запрещенные магические методы

Чтобы объекты Enum не имели какого-либо состояния и чтобы два Enum были сопоставимы, Enum запрещает реализацию нескольких магических методов. Все следующие объявления магических методов недопустимы.

enum Foo public function __get() <> 
public function __set() <>
public function __construct() <>
public function __destruct() <>
public function __clone() <>
public function __sleep() <>
public function __wakeup() <>
public function __set_state() <>
>

// Fatal error: Enum may not include __get in . on line .

Как и ожидалось, были добавлены несколько классов рефлексии для работы с перечислениями: ReflectionEnum, ReflectionEnumUnitCase и ReflectionEnumBackedCase. Также есть новая функция enum_exists, которая делает то, что предполагает ее название - проверяет является ли переданное значение именем класса Enum.

Как и обычные классы и свойства, перечисления и их случаи можно аннотировать с помощью атрибутов . Обратите внимание, что фильтр TARGET_CLASS также будет включать перечисления.

И последнее: перечисления имеют свойство только для чтения, которое в RFC упоминается как деталь реализации и, вероятно, должно использоваться только для целей отладки. Однако об этом все же стоит упомянуть. $enum->name

Источник

Php перечисляемые типы данных

Перечисления похожи на классы и используют те же пространства имён, что и классы, интерфейсы и трейты. Они также могут быть загружены автоматически. Перечисления определяют новый тип, который имеет фиксированное ограниченное количество возможных допустимых значений.

Это объявление создаёт новый перечислимый тип с именем Suit , у которого четыре и только четыре допустимых значения: Suit::Hearts , Suit::Diamonds , Suit::Clubs и Suit::Spades . Переменным может быть присвоено одно из этих допустимых значений. Тип функции может быть проверен на соответствие типу перечисления и в этом случае могут быть переданы только значения этого типа.

// OK
pick_a_card ( $val );
// OK
pick_a_card ( Suit :: Clubs );
// TypeError: pick_a_card(): Argument #1 ($suit) must be of type Suit, string given
pick_a_card ( 'Spades' );
?>

Перечисление может иметь ноль или более вариантов case без ограничений. Перечисление без вариантов синтаксически корректно, хотя и бесполезно.

Для вариантов перечисления применяются те же правила синтаксиса, что и для любой метки в PHP, смотрите Константы.

По умолчанию варианты не поддерживаются скалярным значением. То есть Suit::Hearts не равно "0" . Вместо этого каждый вариант поддерживается одноэлементным объектом с таким именем. Это означает, что:

$a = Suit :: Spades ;
$b = Suit :: Spades ;

Это также означает, что значения перечисления никогда не являются < или >друг с другом, поскольку эти сравнения не имеют смысла для объектов. Сравнения всегда будут возвращать false при работе с вариантами перечисления.

Тип варианта без связанных данных называется "Чистый вариант". Перечисление, которое содержит только чистые варианты, называется чистым перечислением.

Все чистые варианты реализованы как экземпляры своего типа перечисления. Тип перечисления внутренне представлен как класс.

У всех обращений есть свойство, доступное только для чтения, name , которое является именем самого варианта, чувствительным к регистру.

Также можно использовать функции defined() и constant() для проверки существования или чтения регистра перечисления, если имя получено динамически. Однако это не рекомендуется, так как для большинства случаев использования перечислений лучше использовать Типизированные перечисления.

User Contributed Notes

  • Перечисления
    • Обзор перечислений
    • Основы перечислений
    • Типизированные перечисления
    • Методы перечислений
    • Статические методы перечислений
    • Константы перечислений
    • Трейты
    • Значения перечисления в постоянных выражениях
    • Отличия от объектов
    • Список значений
    • Сериализация
    • Почему перечисления не расширяемы
    • Примеры

    Источник

Оцените статью