Symfony: request processing in the API

  • Tutorial
image

I think it’s not a secret for many that the Form component is not suitable for working in the API,
everyone invents his own bike to replace, I decided to share one of these bikes. I do not pretend to be the “best decision”, but if my decision is useful to someone, or if I gain new knowledge, it will be very cool.

In our API, each request is processed using a model, it does not matter whether it is the essence of a doctrine or just a class. Therefore, the solution is built around annotations within these models.

A model might look something like this:

Model listing
city;
    }
    /**
     * @param mixed $value
     */
    public function setCity($value)
    {
        $this->city = $value;
        return $this;
    }
    /**
     * @return string
     */
    public function getQuery()
    {
        return $this->query;
    }
    /**
     * @param string $value
     */
    public function setQuery($value)
    {
        $this->query = $value;
        return $this;
    }
}


The annotation takes the following parameters:
- name (optional parameter, name field in the request)
- type (optional parameter, field type, possible values: string, integer, float, boolean, timestamp, array, entity, array_of_entity)
- groups (not a required parameter, the scope of the request, is needed if the same model is used in different places, but with a different set of fields)

And now what it looks like in the controller:

/** @var Request $request */
$request = $this->get('request');
$data = $request->getRealMethod() == 'GET' ? $request->query->all() : $request->request->all();
/** @var DataMapperManager $manager */
$manager = $this->get('data_mapper.manager');
$model = $manager
    ->setGroups($groups)
    ->setValidationGroups($validationGroups)
    ->setIsClearMissing($clearMissing)
    ->setIsValidate(true)
    ->handle($model, $data);


The manager itself will map all the data to the model, run the validation, and if it does not pass, it will throw an exception.

If we talk about real use, then all the controller code is taken out to the base controller, and inside the real action code it becomes extremely small:

public function createAction()
{
    $user = $this->getUser();
    $entity = $this->save($this->handleRequest(new Common\Entity\Blog\Post($this->getUser())));
    $this->getNotificationManager()->notifyModerators($entity);
    return $entity;
}


Project code:
- github: github.com/Troytft/data-mapper
- packagist: packagist.org/packages/troytft/data-mapper-bundle

Also popular now: