-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
RequestDataObject as in java spring #46991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think this feature is very useful, but need add use case for validate json structure |
I investigated this some times ago and it felt like it would be complicated to add to the core. On the other hand, one could implement its own services to validate requests payload using Symfony’s validator and hydrating the corresponding object. (The reason I feel like this is that this process would be highly specific to your application.) Add a custom value resolver and you’re done. You may also be interested by cuyz/valinor |
In my recent project I did it like this. Define request structureThat's very simple case, but I guess it's enough to demonstrate the general idea {
"productId": "Integer"
} Define request at backendfinal class DeleteProductQuery
{
#[Assert\Positive]
public int $productId;
} Define response at backendIn this case there are two of them first one is empty ('coz I need only to indicate that operation was a success) final class EmptyResponse implements ApiResponseInterface
{
} second one for errors (generic) final class ErrorsResponse implements ApiResponseInterface
{
/** @param string[] $errors */
public function __construct(public readonly array $errors)
{
}
} Stich everything together in controllertry {
/** @var DeleteProductQuery $query */
$query = $serializer->deserialize($request->getContent(), DeleteProductQuery::class, 'json');
} catch (NotEncodableValueException $e) {
// getSimpleErrorApiResponse does a bit of extra work, but inside relies on ErrorsResponse
return $this->getSimpleErrorApiResponse("incorrect json: {$e->getMessage()}")
->setStatusCode(Response::HTTP_BAD_REQUEST);
}
$validationResponse = $this->getValidationResponseForAPI($validator->validate($query));
if ($validationResponse !== null) {
return $validationResponse;
}
try {
// $command is a standalone service which does all the work
$command->execute($query, $currentUser);
} catch (GenericCommandException $e) {
return $this->getSimpleErrorApiResponse($e->getMessage())
->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
}
return $this->getApiResponse(new EmptyResponse()); Both ...Thought about generalizing it, but never really get around to it 😅 Step to a right direction probably would be
In my case that would take care of first part (creating p.s.
|
@Philosoft it seems you use the term “query” too broadly: in CQS terminology your Also your example does not handle missing keys (which would result in an invalid object) neither wrong types (it would crash as you don’t catch Anyways there certainly would be way to generalize individual use cases but I feel like they would diverge too much to create a one-fit-all solution 🤔 |
if we use CQS terminology we must think about supporting both types:
Examples: class AddContactCommand
{
private FullName $fullName;
private Gender $gender;
private ?DateTimeZone $dateTimeZone;
private ?Birthday $birthday;
private ?array $externalIds;
...
} query class ContactsFilter
{
private ?UuidInterface $id;
/**
* @var array<string,string>|null
*/
private ?array $externalSystemIds;
} If we talk about READ model we must also think about pagination \ filtering \ ordering elements
Does anybody work with ApiPlatform and can add related links with documentation \ example? |
@MatTheCat just finished generalizing for my case. It's not CQS really, "query" is just the best term we come up with for generally describing request "in rigid format" from frontend 😅 I agree that my example is flawed (I was in a hurry to contribute "a great idea") and just ended up making a fool of myself 🤦♂️ For generalizing on "framework level" I think there will be too many opinionated choices, so it'd turn out to be form requests from laravel |
That's exactly what I was thinking! ParamConverter:
RequestDataObject:
ProductController::closeAction
I'm using this now and I thought that it would be possible to make a symfony package out of it, because if something were to happen to it, there would be no support for future symfony packages! |
I have implemented something similar in my small project. In the controller I use an attribute to which I pass as parameter the class of the RequestClass. A subscriber then loads the post content and validates it using the RequestClass. Subsequently, an instance of the RequestClass, with the values of the request, is passed as an argument to the controller method. If the validation fails, the call throws a bad request exception. Example: class IndexAction {
#[RequestValidator(class: IndexRequest::class)]
public function __invoke(IndexRequest $request) {
...
}
} class IndexRequest {
#[Assert\NotNull]
#[Assert\Type(type: 'string')]
public $username
public function getUsername(): string {
return $this->string;
}
} |
I think we can close this issue through #49138 |
Description
As it is included in FOSRest and ApiPlatfom, I would be happy if there was a native symfony component. Actually, the main point is to be able to create a RequestDataObject from the Request with the help of a serializer. Of course, it can also be projected now, but all of them are external packages.
Example
POST: /foo/bar/{barId}?status=active
FooBarRequestData:
Serialize an Object from the Symfony Request data
The text was updated successfully, but these errors were encountered: