1. Go to this page and download the library: Download taranovegor/searcher-bundle library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
use Symfony\Component\Validator\Constraints as Assert;
use Taranovegor\SearcherBundle\Configurator\SearchConfigurator;
use Taranovegor\SearcherBundle\Doctrine\DoctrineSearchableDefinitionInterface;
use Taranovegor\SearcherBundle\Enum\FilterOperator;
final class TaskSearchDefinition implements DoctrineSearchableDefinitionInterface
{
public function getEntityClass(): string
{
return Task::class;
}
public function configure(SearchConfigurator $config): void
{
$config->addFilter('status', [FilterOperator::Eq, FilterOperator::In])
->addConstraint(new Assert\Choice(choices: ['backlog', 'in_progress', 'done']));
$config->addFilter('title', [FilterOperator::Like]);
$config->addSortable('createdAt');
$config->paginable(maxLimit: 100, defaultLimit: 20);
}
}
use Taranovegor\SearcherBundle\Attribute\MapSearch;
use Taranovegor\SearcherBundle\Dto\SearchQuery;
use Taranovegor\SearcherBundle\SearcherInterface;
#[Route('/tasks', methods: ['GET'])]
public function list(
#[MapSearch(TaskSearchDefinition::class)] SearchQuery $query,
SearcherInterface $searcher,
): Response {
$result = $searcher->search($query);
// $result->getData() — matched entities
// $result->getPagination() — limit/offset/total, or null when the
// definition did not call paginable()
}
$config->addFilter('code', [FilterOperator::Eq])
->setInputTransformer(UppercaseTransformer::class); // FilterInputTransformerInterface, or a closure
$config->addFilter('tag', [FilterOperator::Eq])
->setHandler(TagNameFilterHandler::class); // FilterHandlerInterface, or a closure
use Taranovegor\SearcherBundle\Context\FilterContextInterface;
use Taranovegor\SearcherBundle\Definition\FilterHandlerInterface;
use Taranovegor\SearcherBundle\Doctrine\DoctrineFilterContext;
use Taranovegor\SearcherBundle\Enum\OperatorInterface;
final class TagNameFilterHandler implements FilterHandlerInterface
{
public function __invoke(FilterContextInterface $context, OperatorInterface $operator, mixed $value): void
{
if (!$context instanceof DoctrineFilterContext) {
throw new \InvalidArgumentException('This handler only supports the Doctrine backend.');
}
$param = $context->uniqueParameterName('tag');
$context->join(sprintf('%s.tags', $context->getRootAlias()), 'tag')
->andWhere($context->expr()->like('tag.name', ":$param"))
->setParameter($param, "%$value%");
}
}
use Taranovegor\SearcherBundle\Doctrine\DistinctSearchableDefinitionInterface;
final class StoreSearchDefinition implements DoctrineSearchableDefinitionInterface, DistinctSearchableDefinitionInterface
{
// ...
}
use Taranovegor\SearcherBundle\Dto\SearchCriteriaDecorator;
use Taranovegor\SearcherBundle\Model\FilterCondition;
use Taranovegor\SearcherBundle\Enum\FilterOperator;
$searchable = SearchCriteriaDecorator::wrap($query)
->withFilter(new FilterCondition('ownerId', FilterOperator::Eq, $user->getId()));
$result = $searcher->search($searchable);