Symfony - validate empty query parameter values
Asked Answered
P

5

14

I am using the FOSRestBundle and was wondering is it possible to validate against empty query parameters using annotations?

For example when calling: /comments/1 an exception is thrown since both dealId and source query parameters haven't been set.

However calling /comments/1?dealId=1&source= is fine even though the source value hasn't ben set and doesn't match the regex outlined in the annotation.

Controller function:

/**
 * Get a single comment.
 *
 * @Annotations\QueryParam(name="dealId", requirements="\d+", strict=true, description="The deal the comments belong to.")
 * @Annotations\QueryParam(name="source", requirements="(forum|blog)", strict=true, description="The source of the comments.")
 *
 * @Annotations\View()
 *
 * @Annotations\Get("/comments/{id}", requirements={"id" = "\d+"})
 *
 */
public function getCommentAction(Request $request, ParamFetcherInterface $paramFetcher, $id)
{
    $dealId = $paramFetcher->get('dealId');
    $source = $paramFetcher->get('source');

    // TODO: Implement


    return [ 'id' => $id, 'dealId' => $dealId, 'source' => $source ];
}

Update

I raised this issue on the FOSRestBundle's GitHub repo too and it looks as if what I am asking for is currently not possible due to the limitations of the Regex validator that is being used.

https://github.com/FriendsOfSymfony/FOSRestBundle/issues/814#issuecomment-49696288

Patagonia answered 8/7, 2014 at 15:26 Comment(1)
As stated in the comment below - use allowBlank=false in the annotation.Behrens
A
3

If you want to force your parameters to be checked, you can change config file as explained in the documentation, Here is the sample:

fos_rest: param_fetcher_listener: force

Then you can set other options like strict, nullable accordingly.

See more details here :

http://symfony.com/doc/current/bundles/FOSRestBundle/configuration-reference.html (archive.org) https://symfony.com/doc/3.x/bundles/FOSRestBundle/index.html#config-reference https://symfony.com/doc/3.x/bundles/FOSRestBundle/annotations-reference.html

Argentous answered 12/9, 2015 at 21:18 Comment(0)
J
2

Just use the allowBlank option of the QueryParam. In your case you would set the allowBlank to false to get the expected behaviour:

The allowBlank option is NOT YET in the FOSRestBundle, but I provided a patch to the FOSRestBundle which has a good chance to land in the next release, version 1.5.0 of the bundle.

This is how your Controller would look like:

/**
 * Get a single comment.
 *
 * @Annotations\QueryParam(name="dealId", requirements="\d+", strict=true, description="The deal the comments belong to.")
 * @Annotations\QueryParam(name="source", requirements="(forum|blog)", strict=true, allowBlank=false, description="The source of the comments.")
 *
 * @Annotations\View()
 *
 * @Annotations\Get("/comments/{id}", requirements={"id" = "\d+"})
 *
 */
public function getCommentAction(Request $request, ParamFetcherInterface $paramFetcher, $id)
{
    $dealId = $paramFetcher->get('dealId');
    $source = $paramFetcher->get('source'); 
}
Jhansi answered 20/11, 2014 at 19:45 Comment(0)
S
1

@Annotations\QueryParam expects a nullable parameter to be set (true or false) if the strict parameter is used. Try setting it.

I guess you want:

@Annotations\QueryParam(name="dealId", requirements="\d+", strict=true, nullable=false, description="The deal the comments belong to.")
@Annotations\QueryParam(name="source", requirements="(forum|blog)", strict=true, nullable=false, description="The source of the comments.")

Also read more about QueryParam in the docs.

Subacid answered 15/7, 2014 at 15:17 Comment(8)
Alas having the nullable parameter to be set doesn't fix the issue and passing through e.g. ..&source= passes when it should fail :(Patagonia
First things first: do you still have the exception?Subacid
There is no exception thrown. It just goes through as if it was valid ouputting the result of return [ 'id' => $id, 'dealId' => $dealId, 'source' => $source ];Patagonia
When calling /comments/1 I mean. Was that a problem for you? You didn't specify that.Subacid
When calling /comments/1 an exception is thrown stating that the two parameters must be provided. However if calling with for example /comments/1?dealId=1&source= or /comments/1?dealId=&source=forumit still goes through as if it was valid. Setting nullable to force doesn't change anything which for me feels like it should :(Patagonia
Setting nullable ok but with which value?Subacid
I've tried with both true and false to no avail.Patagonia
Let us continue this discussion in chat.Patagonia
E
1

The tricky part is allowing source and dealId to be empty but I think it's possible by adding these parameters to your route (so they must be specified in order to access the controller) and using a string prefix for each parameter (i.e. dealid_ and source_), so it's possible to specify an empty value.

You'll also need to modify the regex requirements to allow empty values.

/**
 * Get a single comment.
 *
 * @Annotations\View()
 * @Annotations\Get("/comments/{id}/dealid_{dealId}/source_{source}", 
 *    requirements={"id" = "\d+", "dealId" = "\d*", "source" = "(forum|blog)*"})
 */
public function getCommentAction(Request $request, 
    ParamFetcherInterface $paramFetcher, $id, $dealId, $source) 
{
    return [ 'id' => $id, 'dealId' => $dealId, 'source' => $source ];
}
Ellswerth answered 16/7, 2014 at 10:40 Comment(2)
Neither of them must be empty, they must be both provided.Patagonia
@Patagonia if I understand correctly, they must be specified but they may be specified as the empty stringEllswerth
M
-3

I am not familiar with symfony, but I think a simple

$dealId = isset($dealId) ? $dealId : '';

Would help your problem

Mansard answered 15/7, 2014 at 15:7 Comment(3)
I really want to have it done within the annotations and it must be something the framework allows.Patagonia
Unfortunately it will not help even without framework. It was a solution when GET params were converted to global variables (can be configured in php.ini), but not in any other case. And testing like isset($_GET['param']) with Symfony is also not a good practice. Symfony has Request object for dealing with request params, but OP wants to manage it using FOS Bundle annotations. And if you announced variable above it will be definitely isset() unless NULL.Irredentist
This is not only unrelated to the topic but also a bad practice which wouldn't even work with PHP > 5.2.Conjunctive

© 2022 - 2024 — McMap. All rights reserved.