Урок 9: Работа с API в Symfony

В 9-ом уроке мы изучим одну из самых востребованных тем современной веб-разработки, это создание API на Symfony. Мы разберем, как строить RESTful API, сериализовать данные, защищать endpoints с помощью JWT и документировать всё это с помощью Swagger.

Создание RESTful API

RESTful API это стандарт для обмена данными между клиентом и сервером. В Symfony его можно реализовать быстро и элегантно.

1. Настройка маршрутов

Создадим контроллер для работы с сущностью Product:

bash
php bin/console make:controller ProductController

В файле src/Controller/ProductController.php добавим методы для CRUD:

php
#[Route('/api/products', name: 'api_products', methods: ['GET'])]
public function index(ProductRepository $repository): JsonResponse
{
    $products = $repository->findAll();
    return $this->json($products);
}

#[Route('/api/products/{id}', name: 'api_product_show', methods: ['GET'])]
public function show(Product $product): JsonResponse
{
    return $this->json($product);
}

Маршруты готовы! Теперь по адресу /api/products вы получите список товаров в JSON.

2. Работа с HTTP-методами

Добавим обработку POST, PUT и DELETE:

php
#[Route('/api/products', name: 'api_product_create', methods: ['POST'])]
public function create(Request $request, EntityManagerInterface $em): JsonResponse
{
    $data = json_decode($request->getContent(), true);
    $product = new Product();
    $product->setName($data['name']);
    $product->setPrice($data['price']);
    
    $em->persist($product);
    $em->flush();
    
    return $this->json($product, 201);
}

#[Route('/api/products/{id}', name: 'api_product_update', methods: ['PUT'])]
public function update(Product $product, Request $request, EntityManagerInterface $em): JsonResponse
{
    $data = json_decode($request->getContent(), true);
    $product->setName($data['name'] ?? $product->getName());
    $product->setPrice($data['price'] ?? $product->getPrice());
    
    $em->flush();
    
    return $this->json($product);
}

#[Route('/api/products/{id}', name: 'api_product_delete', methods: ['DELETE'])]
public function delete(Product $product, EntityManagerInterface $em): JsonResponse
{
    $em->remove($product);
    $em->flush();
    
    return $this->json(null, 204);
}

Практическая задача:

Создайте CRUD для сущности User с полями email и password.
Подсказка: Используйте make:entity User для генерации сущности.

Сериализация данных с Serializer

Компонент Serializer преобразует объекты в JSON/XML и обратно. Подключим его:

yaml
# config/packages/framework.yaml
framework:
    serializer: { enable_annotations: true }

1. Группы сериализации

Допустим, мы не хотим отдавать поле password пользователя. Добавим аннотацию в сущность:

php
use Symfony\Component\Serializer\Annotation\Groups;

class User
{
    #[Groups(['public'])]
    private string $email;
    
    private string $password;
}

В контроллере укажем группу:

php
return $this->json($user, 200, [], ['groups' => ['public']]);

2. Кастомные сериализаторы

Создадим свой сериализатор для преобразования даты:

php
use Symfony\Component\Serializer\SerializerInterface;

public function show(Product $product, SerializerInterface $serializer): Response
{
    $data = $serializer->serialize($product, 'json', [
        'datetime_format' => 'Y-m-d H:i:s',
    ]);
    
    return new Response($data, 200, ['Content-Type' => 'application/json']);
}

Практическая задача:

Создайте группу admin, которая включает поле createdAt для сущности Product.

JWT-аутентификация для API

JWT (JSON Web Token) популярный метод аутентификации для API. Установим необходимые пакеты:

bash
composer require lexik/jwt-authentication-bundle

1. Генерация ключей

bash
mkdir config/jwt
openssl genpkey -out config/jwt/private.pem -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096
openssl pkey -in config/jwt/private.pem -out config/jwt/public.pem -pubout

2. Настройка security.yaml

yaml
# config/packages/security.yaml
security:
    firewalls:
        api:
            pattern: ^/api
            stateless: true
            jwt: ~

    access_control:
        - { path: ^/api/login, roles: PUBLIC_ACCESS }
        - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }

3. Создание токена

Добавим метод аутентификации:

php
#[Route('/api/login', name: 'api_login', methods: ['POST'])]
public function login(): JsonResponse
{
    // Аутентификация через событие Symfony
    return $this->json(['token' => 'ВАШ_JWT_ТОКЕН']);
}

Практическая задача:

Реализуйте эндпоинт /api/login, который возвращает JWT-токен после успешной аутентификации.

Документирование API с Swagger/OpenAPI

Swagger инструмент для автоматической генерации документации. Установим бандл:

bash
composer require nelmio/api-doc-bundle

1. Настройка конфигурации

Добавим аннотации к контроллерам:

php
use OpenApi\Annotations as OA;

/**
 * @OA\Tag(name="Products")
 */
class ProductController extends AbstractController
{
    /**
     * @OA\Response(
     *     response=200,
     *     description="Возвращает список товаров"
     * )
     */
    #[Route('/api/products', methods: ['GET'])]
    public function index(): JsonResponse
    {
        // ...
    }
}

2. Просмотр документации

Перейдите по адресу /api/doc. Вы увидите интерактивную Swagger-документацию!

Практическая задача:

Опишите в Swagger все endpoints для сущности User.

Итоги 9-го урока

Сегодня мы прошли ключевые этапы работы с API в Symfony, от создания RESTful-маршрутов до защиты JWT и документирования. Теперь вы можете создавать мощные и безопасные API для своих проектов.

Хотите освоить Symfony от А до Я? Перейти к полному курсу

Поделиться статьей:
Поддержать автора блога

Поддержка автора осуществляется с помощью специальной формы ниже, предоставленной сервисом «ЮMoney». Все платёжные операции выполняются на защищённой странице сервиса, что обеспечивает их корректность и полную безопасность.

Персональные рекомендации
Оставить комментарий