Skip to content

Instantly share code, notes, and snippets.

@philippecarle
Created September 18, 2018 07:26
Show Gist options
  • Save philippecarle/d99d71b9be62a69b2eb1cf3690957006 to your computer and use it in GitHub Desktop.
Save philippecarle/d99d71b9be62a69b2eb1cf3690957006 to your computer and use it in GitHub Desktop.
Discriminator Filter for API Platform
<?php
declare(strict_types=1);
namespace AppBundle\Filter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\QueryBuilder;
use Psr\Log\LoggerInterface;
class DiscriminatorFilter extends AbstractContextAwareFilter
{
const FILTER_RESOURCE_TYPE_PROPERTY = 'resourceType';
/**
* @var ResourceMetadataFactoryInterface
*/
private $resourceMetadataFactory;
public function __construct(
ManagerRegistry $managerRegistry,
ResourceMetadataFactoryInterface $resourceMetadataFactory,
LoggerInterface $logger = null,
array $properties = null
) {
parent::__construct($managerRegistry, null, $logger, $properties);
$this->resourceMetadataFactory = $resourceMetadataFactory;
}
/**
* {@inheritdoc}
*/
public function getDescription(string $resourceClass): array
{
return [
static::FILTER_RESOURCE_TYPE_PROPERTY => [
'property' => static::FILTER_RESOURCE_TYPE_PROPERTY,
'type' => 'string',
'required' => false,
],
];
}
/**
* {@inheritdoc}
*/
protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = [])
{
if ($property !== static::FILTER_RESOURCE_TYPE_PROPERTY) {
return;
}
/** @var ObjectManager $manager */
$manager = $this->managerRegistry->getManagerForClass($resourceClass);
$classMetadataFactory = $manager->getMetadataFactory();
/** @var ClassMetadataInfo $classMetadata */
$classMetadata = $classMetadataFactory->getMetadataFor($resourceClass);
foreach ($classMetadata->discriminatorMap as $discriminator => $entityClass) {
$metadata = $this->resourceMetadataFactory->create($entityClass);
if ($metadata->getShortName() === $value) {
$alias = $queryBuilder->getAllAliases()[0];
$queryBuilder->andWhere($alias.' INSTANCE OF :instance');
$queryBuilder->setParameter('instance', $discriminator);
return;
}
}
$queryBuilder->where('1=0');
}
}
@khaledBou
Copy link

I tried this class, i created a service and i call the service in my entity :

/**
 * A Contact
 *
 * @ApiResource(attributes={
 *     "normalization_context"={"groups"={"contact:read"}},
 *     "denormalization_context"={"groups"={"contact:write"}},
 *     "filters"={"custom.search_filter"} // call the Discriminator filter
 * })
 *

It works for me, i can filter with the DiscriminatorColumn name

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment