Skip to content

Latest commit

 

History

History
160 lines (128 loc) · 4.41 KB

getting-started.md

File metadata and controls

160 lines (128 loc) · 4.41 KB

Fazland - DtoManagementBundle

Think about these points:

  • Have you ever struggled against very long controllers' actions?

  • Have you ever written services in order to create, read update, delete entities?

  • Have you ever hated coupling entities to relative types (i.e. implementing \Symfony\Component\Form\FormTypeInterface or \Symfony\Component\Form\AbstractType)?

DTOs (Data Transfer objects) are simple objects that can prevent the problems just listed. It is obvious that this is a Design Pattern and it can be a solution or a methodology for your application. It is not necessary the right or the only way to write your application.

An example

Let's think about a small scenario: we have to implement a simple CRUD API that let the users manage an item list (create, read, update and delete items).

With DtoManagementBundle the ItemController will be really simple, like the following.

<?php declare(strict_types=1);

namespace App\Controller;

use App\Entity;
use App\Model\Interfaces\Item\ItemInterface;
use App\Model\Interfaces\Item\ItemListInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class ItemController extends AbstractController
{
    /**
     * Retrieves the Items list.
     *
     * @Route(path="/items", methods={"GET"})
     *
     * @param Request            $request
     * @param ItemListInterface $dto
     *
     * @return Response
     */
    public function listAction(Request $request, ItemListInterface $dto): Response
    {
        $results = $dto->handleRequest($request);

        $response = // serialize the list into a Response

        return $response;
    }

    /**
     * Posts an Item.
     *
     * @Route(path="/items", methods={"POST"})
     *
     * @param Request       $request
     * @param ItemInterface $dto
     *
     * @return Response
     */
    public function postAction(Request $request, ItemInterface $dto): Response
    {
        $result = $dto->handleRequest($request);

        if (! $result instanceof FormInterface) {
            $dto->commit();
        }

        $response = // serialize the item or the form into a Response

        return $response;
    }

    /**
     * Gets an Item.
     *
     * @Route(path="/item/{id}", methods={"GET"})
     *
     * @param Entity\Item\Item $item
     * @param ItemInterface    $dto
     *
     * @return Response
     */
    public function getAction(Entity\Item\Item $item, ItemInterface $dto): Response
    {
        $dto->setItem($item);

        $response = // serialize the item into a Response

        return $response;
    }

    /**
     * Patches an Item.
     *
     * @Route(path="/item/{id}", methods={"PATCH"})
     *
     * @param Request          $request
     * @param Entity\Item\Item $item
     * @param ItemInterface    $dto
     *
     * @return Response
     */
    public function patchAction(Request $request, Entity\Item\Item $item, ItemInterface $dto): Response
    {
        $result = $dto
            ->setItem($item)
            ->handleRequest($request)
        ;

        if (! $result instanceof FormInterface) {
            $dto->commit();
        }

        $response = // serialize the item into a Response

        return $response;
    }

    /**
     * Deletes an Item.
     *
     * @Route(path="/item/{id}", methods={"DELETE"})
     *
     * @param Entity\Item\Item $item
     * @param ItemInterface    $dto
     *
     * @return Response
     */
    public function deleteAction(Entity\Item\Item $item, ItemInterface $dto): Response
    {
        $dto->setItem($item);

        $dto->remove();

        $response = // serialize the item into a Response

        return $response;
    }
}

Simple, isn't it?

DtoManagementBundle comes with the ApiModelParamConverter which will inject in your action the right implementation (the version) of the DTO.

In this way you can version your endpoints without changing a single line of code of your controller actions.

Let's see how it is configured and how it works.