Найти в Дзене
Symfony Topsite Web

Использование Enum в Symfony

PHP 8.1 представляет официальную поддержку Enum. Doctrine привнесла поддержку типа Enum в свою структуру ORM, а Symfony добавила поддержку сериализации и десериализации типа Enum. Пришло время перевести ваши проекты на использование PHP Enum, если вы используете сторонние решения для перечисления. Чтобы использовать PHP Enum, вам необходимо обновиться до PHP 8.1 и установить версию PHP 8.1 в файле composer проекта. {
//...
"require": {
"php": ">=8.1",
//...
}
} Создание перечисляемого класса Например, мы добавим Status к Post сущности и определим несколько фиксированных значений статуса поста. namespace App\Entity; enum Status: string
{
case Draft = "DRAFT";
case PendingModerated = "PENDING_MODERATED";
case Published = "PUBLISHED";
} Здесь мы используем перечисление, поддерживаемое строкой, добавляем поле в Post класс. #[Column(type: "string", enumType: Status::class)]
private Status $status; Обратите внимание, установите enumType в качеств
Оглавление

PHP 8.1 представляет официальную поддержку Enum. Doctrine привнесла поддержку типа Enum в свою структуру ORM, а Symfony добавила поддержку сериализации и десериализации типа Enum.

Пришло время перевести ваши проекты на использование PHP Enum, если вы используете сторонние решения для перечисления.

Чтобы использовать PHP Enum, вам необходимо обновиться до PHP 8.1 и установить версию PHP 8.1 в файле composer проекта.

{
//...
"require": {
"php": ">=8.1",
//...
}
}

Создание перечисляемого класса

Например, мы добавим Status к Post сущности и определим несколько фиксированных значений статуса поста.

namespace App\Entity;
enum Status: string
{
case Draft = "DRAFT";
case PendingModerated = "PENDING_MODERATED";
case Published = "PUBLISHED";
}

Здесь мы используем перечисление, поддерживаемое строкой, добавляем поле в Post класс.

#[Column(type: "string", enumType: Status::class)]
private Status $status;

Обратите внимание, установите enumType в качестве Status класса. Он будет хранить значение статуса в виде строки в таблицах базы данных.

В Post конструкторе присвойте статусу значение по умолчанию.

public function __construct()
{
$this->status = Status::Draft;
//...
}

Создание HTTP-метода

Когда мы настраиваем Route атрибут в классе Controller, мы используем буквальное значение для настройки метода HTTP.

#[Route(path: "/{id}", name: "byId", methods: ["GET"])]

Для значения методов доступно только несколько вариантов. Очевидно, что введение Enum обеспечит типобезопасный способ установки значений и уменьшит количество ошибок опечаток.

Создайте Enum с именем HttpMethod.

namespace App\Annotation;
enum HttpMethod
{
case GET;
case POST;
case HEAD;
case OPTIONS;
case PATCH;
case PUT;
case DELETE;
}

Затем выполните рефакторинг Route атрибута и создайте серию атрибутов (Get, Post, Put, Delete и т. д.), которые сопоставляются с различными методами HTTP.

//file : src/Annotation/Get.php
#[Attribute]
class Get extends Route
{
public function getMethods()
{
return [HttpMethod::GET->name];
}}
//file : src/Annotation/Head.php
#[Attribute]
class Head extends Route
{
public function getMethods()
{
return [HttpMethod::HEAD->name];
}}
//file : src/Annotation/Options.php
#[Attribute]
class Options extends Route
{
public function getMethods()
{
return [HttpMethod::OPTIONS->name];
}}
//file : src/Annotation/Patch.php
#[Attribute]
class Patch extends Route
{
public function getMethods()
{
return [HttpMethod::PATCH->name];
}
}
//file : src/Annotation/Post.php
#[Attribute]
class Post extends Route
{
public function getMethods()
{
return [HttpMethod::POST->name];
}
}
//file : src/Annotation/Put.php
#[Attribute]
class Put extends Route
{
public function getMethods()
{
return [HttpMethod::PUT->name];
}
}
//file : src/Annotation/Delete.php
#[Attribute]
class Delete extends Route
{
public function getMethods()
{
return [HttpMethod::DELETE->name];
}
}

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

#[Route(path: "/posts", name: "posts_")]
class PostController extends AbstractController
{
// constructor...
// #[Route(path: "", name: "all", methods: ["GET"])]
#[Get(path: "", name: "all")]
public function all(#[QueryParam] string $keyword,
#[QueryParam] int $offset = 0,
#[QueryParam] int $limit = 20): Response
{
//...
}
// #[Route(path: "/{id}", name: "byId", methods: ["GET"])]
#[Get(path: "/{id}", name: "byId")]
public function getById(Uuid $id): Response
{
//...
}
//#[Route(path: "", name: "create", methods: ["POST"])]
#[Post(path: "", name: "create")]
public function create(#[Body] CreatePostDto $data): Response
{
//...
}
//#[Route(path: "/{id}", name: "update", methods: ["PUT"])]
#[Put(path: "/{id}", name: "update")]
public function update(Uuid $id, #[Body] UpdatePostDto $data): Response
{
//...
}
// #[Route(path: "/{id}/status", name: "update_status", methods: ["PUT"])]
#[Put(path: "/{id}/status", name: "update_status")]
public function updateStatus(Uuid $id, #[Body] UpdatePostStatusDto $data): Response
{
//...
}
//#[Route(path: "/{id}", name: "delete", methods: ["DELETE"])]
#[Delete(path: "/{id}", name: "delete")]
public function deleteById(Uuid $id): Response
{
//...
}

//#[Route(path: "/{id}/comments", name: "commentByPostId", methods: ["GET"])]
#[GET(path: "/{id}/comments", name: "commentByPostId")]
public function getComments(Uuid $id): Response
{
//...
}}