I have been working on a restful api, I would like to know where should I process the payload after been validated. Right now it look something like this:
// src/Controller/ExampleController.php
public function create(Request $request, EntityManagerInterface $manager)
{
// the getPayload gonna return a object representing my data
// already validate, ready to be processed
$data = $this->getPayload()
$exampleEntity = new ExampleEntity();
$exampleEntity
->setUser($this->getUser())
->setBook($data->book);
$manager->persist($exampleEntity);
$manager->flush();
return new JsonResponse($example->getResult());
}
I was adviced to create a service to process the data and don't use direct in the controller. I actually like to separate the data outside the controller, but then should I create a service for each controller? something like this:
// src/Controller/SomeController.php
public function create(Request $request, \App\Service\Example $example)
{
// the getPayload gonna return a object representing my data
// already validate, ready to be processed
$data = $this->getPayload()
$example->setPayload($data);
$example->process();
return new JsonResponse($example->getResult());
}
I have other question, should I validate identifiers, for example if I receive a json body passing the id of a book, if I create a new constraint to verify if the book exist it would require a query in the database (because i'm validating the payload automatically before it gets int he controller) and one more query later to actually create the relation. Example:
// src/Controller/ExampleController.php
public function create(
Request $request,
ExampleReposiry $repository,
EntityManagerInterface $manager)
{
// the getPayload gonna return a object representing my data
// already validate, ready to be processed
$data = $this->getPayload()
$exampleEntity = new ExampleEntity();
$exampleEntity
->setUser($this->getUser())
// $data->book is only the id, not the actually object book
// this is the second time query for the object, the fist
// time was inside the custom constraint that validate
// to see if the id pass is valid.
->setBook($repository->findBy(['id' => $data->book]));
$manager->persist($exampleEntity);
$manager->flush();
return new JsonResponse($example->getResult());
}
Or instead of that I just assume that the id of the book pass is valid and if not I just throw an Exception?
The post that I follow to validate automatically the data here
I was adviced to create a service to process the data and don't use direct in the controller. I actually like to separate the data outside the controller, but then should I create a service for each controller?
Or instead of that I just assume that the id of the book pass is valid and if not I just throw an Exception?
I would separate responsibilities as follows.
ExampleService
class (where business logic takes place) and inject it into ExampleController
. ExampleService
class. ExampleFactory
class (where data mapping takes place) and inject it into ExampleService
. ExampleFactory
so that it returns ExampleEntity
instance. persist
and flush
on ExampleEntity
instance. Assuming that you already injected ExampleRepository
class into ExampleService
class. Then do whatever else you need to do and return Response::HTTP_CREATED
in ExampleController
.
This was my implementation base on what @BentCoder answered. After pass the whole day at work thinking factory or no factory ? I end up trying use factory pattern because:
try out new things (it's a side project so it's ok mess up)
// src/Controller/ExampleController.php public function create(\\App\\Service\\Example $exampleService) { $exampleService->process($this->getPayload()); // .. do something } // src/Service/Example.php public function process(App\\Model\\ExampleInterface $data) { // factory was receive via dependency injection in the constructor $objects = $this->factory->create($data); // .. do something } // src/Model/Example/Create.php class Create implements App\\Model\\ExampleInterface { public $property1; public $property2; } // src/Model/Example/Update.php class Update implements App\\Model\\ExampleInterface { public $property2; } // src/Factory/ExampleFactory.php public function create(App\\Model\\ExampleInterface $data) { if ($data instanceof App\\Model\\Example\\Create::class) ( // .. return a array of instantiated object } elseif ($data instanceof App\\Model\\Example\\Update::class) { // .. returm only one object } }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.