Skip to content

[GraphQL] NumericFilter and RangeFilter can not be defined on the same property #3483

Open
@epourail

Description

@epourail

API Platform version(s) affected: 2.5.4

Description

In my context, i need to enable both RangeFilter and NumericFilter on the same property to have the following filtering option : less than, equals, between and greater than
In such case, the graphql schema will convert both filters in the same way using the property name to identify the filter.

In the following example

/**
 * @ApiResource()
 * @ApiFilter(RangeFilter::class, properties={"age"})
 * @ApiFilter(NumericFilter::class, properties={"age"})
 */
class Dummy
{
   /** @var int $age */
   private $age;

   // ...
}

The REST collection endpoint enables both filters with the syntax /dummies?age=18 and /dummies?age[gt]=18

But the GraphQL endpoint enables only the NumericFilter with the syntax dummies(age: "18") { ... }
(as the RangeFilter uses the syntax dummies(age: {gt: "18"}))

How to reproduce
Here a valid entity declaration

<?php

declare(strict_types=1);

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\RangeFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\NumericFilter;

use Doctrine\ORM\Mapping as ORM;

/**
 * Class Dummy
 * @package App\Entity
 *
 * @ApiResource(
 *     graphql={
 *         "item_query",
 *         "collection_query"
 *     }
 * )
 * @ApiFilter(RangeFilter::class, properties={"age"})
 * @ApiFilter(NumericFilter::class, properties={"age"})
 * @ORM\Entity
 */
class Dummy
{
    /**
     * @var string|null
     * @ApiProperty(iri="http://schema.org/identifier")
     * @ORM\Column(type="guid")
     * @ORM\GeneratedValue(strategy="UUID")
     * @ORM\Id()
     */
    private $id;

    public function getId() 
    {
        return $this->id;
    }

    public function setId($id): void
    {
        $this->id = $id;
    }

    /**
     * @var integer
     * @ApiProperty
     * @ORM\Column(type="integer")
     */
    private $age;

    public function getAge()
    {
        return $this->age;
    }

    public function setAge($age): void
    {
        $this->age = $age;
    }
}

Case 1. Both RangeFilter and NumericFilter

In the entity definition, enabling both the RangeFilter and the NumericFilter the following graphql query is available

{
  dummies(age: 18) {
    edges {
      node {
        id age
      }
    }
  }
}

And the following syntax:

{
  dummies(age: {gt:"18"}) {
    edges {
      node {
        id age
      }
    }
  }
}

raises the error:

{
  "errors": [
    {
      "message": "Field \"dummies\" argument \"age\" requires type Int, found {gt: \"18\"}.",
      "extensions": {
        "category": "graphql"
      },
      "locations": [
        {
          "line": 2,
          "column": 16
        }
      ]
    }
  ]
}

Case 2. Only RangeFilter

In the entity definition, enabling only the RangeFilter (delete the NumericFilter filter declaration) the following graphql query is available

{
  dummies(age: {gt:"18"}) {
    edges {
      node {
        id age
      }
    }
  }
}

And the following syntax:

{
  dummies(age: 18) {
    edges {
      node {
        id age
      }
    }
  }
}

raises the error:

{
  "errors": [
    {
      "message": "Field \"dummies\" argument \"age\" requires type DummyFilter_age, found 18.",
      "extensions": {
        "category": "graphql"
      },
      "locations": [
        {
          "line": 2,
          "column": 16
        }
      ]
    }
  ]
}

Possible Solution

The RangeFilter should supports an eq (and neq) syntax allowing to use, with one filter, all the cases : less than, between, greater than and equal to

Additional Context
Note that using the NumericFilter a numerical value should be defined but using the RangeFilter, a string should be used to define the value.
Should I open another issue ?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions