3 ноя 2020

Enum, spl и причем тут php

#php, #spl, #enum

Enum - перечисление, важный тип данных, позволяющий создавать ограниченные последовательности из идентификаторов. Иными словами, это набор всегда строго определенных значений. В слаботипизированных языках, к которым изначально принадлежит и php, этот тип обычно не реализован. И хотя разработчики уже не первый год просят создать enum в php, создатели этого языка пока не спешат обрадовать сообщество этой возможностью.

Enum, spl и причем тут php

Enum, spl и php

Так было не всегда. До 7 версии в php была, встроенная в spl (стандартная библиотека PHP), возможность эмулировать enum. Это можно было сделать создав свой класс, наследующий от SplEnum. Но, по мере развития языка и движению к строгой типизации, эту возможность было решено исключить. В релиз php 7.0.0 от 3 декабря 2015 г. этот тип данных включен не был.

Однако, сообщество разработчиков всё равно хотело использовать enum тип и создало свои инструменты для этого. И мы рассмотрим их чуть позже в этой статье, а сейчас хочу рассказать, чем же удобен этот тип и какие проблемы он решает.

Для чего нужен enum

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

Первая идея, которая приходит в голову, поместить все продукты в массив:

<?php

$types = [
    'сельская ипотека',
    'автокредит',
    'кредит наличными',
];

Теперь можно создавать страницы с формами, где будет указан тип программы. Рассмотрим пример с "сельская ипотека":

<form>
    <input type="text" name="name" placeholder="Имя">
    <input type="text" name="tel" placeholder="Телефон">
    <input type="text" name="sum" placeholder="Необходимая сумма">
    <input type="hidden" name="type" value="cельская ипотека">
    <button type="submit">Отправить заявку</button>
</form>

Php-скрипт по значению инпута с именем type будет определять разрешенный тип. То есть проводить проверку наличия данной строки в массиве:

<?php

if (in_array($_POST['type'], $types)) {
    // обработка заявки
} else {
    // неверный тип заявки
}

И вот тут нас поджидает самая распространенная ошибка с буквой "с". Догадались какая? Да, в созданной форме строка "cельская ипотека" начинается с английской буквы. Это очень неочевидная и частая ошибка, которую сложно отловить. Пока вы догадаетесь в чем причина, ваш заказчик потеряет много клиентов. Вот тут бы нам и пригодился тип enum.

Эмуляция enum в современном php

Сообщество php-разработчиков не сидело без дела все эти годы и разработало прекрасную библиотеку myclabs/php-enum, которая позволяет создавать классы эмулирующие перечисления. На момент написания статьи, у неё набралось почти 2 тысячи звезд на github и 16,5 миллионов скачиваний.

Как и любую другую современную библиотеку, её можно установить с помощью пакетного менеджера composer. Для этого в консоли нужно выполнить:

composer require myclabs/php-enum

Теперь мы сможем создать перечисление наших продуктов, используя enum тип. Для удобства приведу весь код в одном месте:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
// подключение автолодера
include "vendor/autoload.php";
// подключение пространства имен
use MyCLabs\Enum\Enum;

// наш класс, реализующий enum
class MortgageTypes extends Enum
{
    private const RURAL = 'сельская ипотека';
    private const AUTO = 'автокредит';
    private const CASH = 'кредит наличными';
}
?>
<form>
    <input type="text" name="name" placeholder="Имя">
    <input type="text" name="tel" placeholder="Телефон">
    <input type="text" name="sum" placeholder="Необходимая сумма">
    <input type="hidden" name="type" value="<?= new MortgageTypes(MortgageTypes::RURAL())?>">
    <button type="submit">Отправить заявку</button>
</form>

Обратите внимание на строку 19, значение аттрибута value будет "сельская ипотека", на этот раз, с правильной буквой "с". А проверить это значение можно с помощью простого кода:

<?php

if (MortgageTypes::isValid($_POST['type'])) {
    // обработка заявки
} else {
    // неверный тип заявки
}

Такой код значительно лучше читается и огранизован с помощью классов, что добавляет + в карму и упрощает тестирование. Эмуляция типа enum также позволяет нам оградить своё приложение от возможных багов, а заказчика от непредвиденных потерь. Для этого была использована сторонняя библиотека, хотя в идеальном мире этот тип данных мог бы быть и встроен в php. Надеюсь, разработчики этого языка в ближайшее время услышат сообщество. Ну а мы с вами знаем что с этим делать.

Все статьи

© 2020-2021 Александр Пантелеев