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

Malachi
  • 33,142
  • 18
  • 63
  • 96

5 Answers5

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

Kamafeather
  • 8,663
  • 14
  • 69
  • 99
orhankutlu
  • 820
  • 8
  • 20
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'); 
}
mosch
  • 1,005
  • 1
  • 12
  • 24
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.

dlondero
  • 2,539
  • 1
  • 24
  • 33
  • Alas having the `nullable` parameter to be set doesn't fix the issue and passing through e.g. `..&source=` passes when it should fail :( – Malachi Jul 16 '14 at 11:45
  • First things first: do you still have the exception? – dlondero Jul 17 '14 at 14:57
  • 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 ];` – Malachi Jul 17 '14 at 15:01
  • When calling `/comments/1` I mean. Was that a problem for you? You didn't specify that. – dlondero Jul 17 '14 at 15:03
  • 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=forum`it still goes through as if it was valid. Setting nullable to force doesn't change anything which for me feels like it should :( – Malachi Jul 17 '14 at 15:13
  • Setting `nullable` ok but with which value? – dlondero Jul 17 '14 at 15:15
  • I've tried with both `true` and `false` to no avail. – Malachi Jul 17 '14 at 15:18
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57511/discussion-between-malachi-and-dlondero). – Malachi Jul 17 '14 at 15:21
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 ];
}
FuzzyTree
  • 32,014
  • 3
  • 54
  • 85
-3

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

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

Would help your problem

Limiter
  • 497
  • 3
  • 11
  • I really want to have it done within the annotations and it must be something the framework allows. – Malachi Jul 16 '14 at 11:45
  • 1
    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_. – Paul T. Rawkeen Apr 22 '15 at 13:45
  • This is not only unrelated to the topic but also a bad practice which wouldn't even work with PHP > 5.2. – Nicolas Aug 31 '16 at 13:29