Я создаю прототип REST API в Symfony2 с FOSRestBundle, используя JMSSerializerBundle для сериализации сущностей. С запросом GET я могу использовать функциональность ParamConverter SensioFrameworkExtraBundle для получения экземпляра объекта на основе параметра запроса id, а при создании нового объекта с запросом POST я могу использовать преобразователь тела FOSRestBundle для создания нового экземпляра объекта на основе данные запроса. Но когда я хочу обновить существующий объект, использование преобразователя FOSRestBundle дает объект без идентификатора (даже если идентификатор отправляется с данными запроса), поэтому, если я сохраняю его, он создаст новый объект. И использование преобразователя SensioFrameworkExtraBundle дает мне исходный объект без новых данных, поэтому мне пришлось бы вручную получать данные из запроса и вызывать все методы установки для обновления данных объекта.
Итак, мой вопрос: каков предпочтительный способ справиться с этой ситуацией? Похоже, должен быть какой-то способ справиться с этим, используя (де) сериализацию данных запроса. Я упустил что-то, связанное с сериализатором ParamConverter или JMS, который справился бы с этой ситуацией? Я понимаю, что есть много способов делать такие вещи, и ни один из них не подходит для каждого случая использования, просто ищите что-то, что подходит для такого быстрого прототипирования, которое вы можете сделать с помощью ParamConverter и минимального кода, необходимого для написания в контроллерах/сервисах.
Вот пример контроллера с действиями GET и POST, как описано выше:
namespace My\ExampleBundle\Controller;
use My\ExampleBundle\Entity\Entity;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\View\View;
class EntityController extends Controller
{
/**
* @Route("/{id}", requirements={"id" = "\d+"})
* @ParamConverter("entity", class="MyExampleBundle:Entity")
* @Method("GET")
* @Rest\View()
*/
public function getAction(Entity $entity)
{
return $entity;
}
/**
* @Route("/")
* @ParamConverter("entity", converter="fos_rest.request_body")
* @Method("POST")
* @Rest\View(statusCode=201)
*/
public function createAction(Entity $entity, ConstraintViolationListInterface $validationErrors)
{
// Handle validation errors
if (count($validationErrors) > 0) {
return View::create(
['errors' => $validationErrors],
Response::HTTP_BAD_REQUEST
);
}
return $this->get('my.entity.repository')->save($entity);
}
}
И в config.yml у меня есть следующая конфигурация для FOSRestBundle:
fos_rest:
param_fetcher_listener: true
body_converter:
enabled: true
validate: true
body_listener:
decoders:
json: fos_rest.decoder.jsontoform
format_listener:
rules:
- { path: ^/api/, priorities: ['json'], prefer_extension: false }
- { path: ^/, priorities: ['html'], prefer_extension: false }
view:
view_response_listener: force