phpsymfonyapi-platform.com

Filter required in Api Platform


Im using API Platform and I have defined a custom filter following https://api-platform.com/docs/core/filters/#creating-custom-filters

It works ok, but I need to that filter is required everytime that application do a GET HTTP Request of particular entity (where the filter is set).

I have check this code:

// This function is only used to hook in documentation generators (supported by Swagger and Hydra)
public function getDescription(string $resourceClass): array
{
    if (!$this->properties) {
        return [];
    }

    $description = [];
    foreach ($this->properties as $property => $strategy) {
        $description["similar_$property"] = [
            'property' => $property,
            'type' => 'string',
            'required' => false,
            'swagger' => [
                'description' => 'Filter using a similar postgres function.',
                'name' => $property,
                'type' => 'string',
            ],
        ];
    }

    return $description;
}

Although getDescription has a required field, it only works for api documentation and not for HTTP Request


Solution

  • You can enforce a filter through the event system.

    /**
     * @ApiResource
     */
    class Resource {
        ...
    }
    
    <?php
    
    namespace App\EventSubscriber;
    
    use ApiPlatform\Core\EventListener\EventPriorities;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\HttpKernel\Event\ControllerEvent;
    use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
    use Symfony\Component\HttpKernel\KernelEvents;
    
    class ResourceReadSubscriber implements EventSubscriberInterface
    {
        /**
         * @return array The event names to listen to
         */
        public static function getSubscribedEvents()
        {
            return [
                KernelEvents::CONTROLLER => [
                    ['hasFilter', EventPriorities::PRE_READ],
                ],
            ];
        }
    
        public function hasFilter(ControllerEvent $event)
        {
            // first check if this affects the requested resource
            $resource = $event->getRequest()->attributes->get('_api_resource_class');
    
            if (Resource::class !== $resource) {
                return;
            }
    
            // second check if this is the get_collection controller
            $controller = $event->getRequest()->attributes->get('_controller');
    
            if ('api_platform.action.get_collection' !== $controller) {
                return;
            }
    
            // third validate the required filter is set
            // we expect a filter via GET parameter 'filter-query-parameter'
            if (!$event->getRequest()->query->has('filter-query-parameter')) {
                throw new BadRequestHttpException('Filter is required');
            }
        }
    }