composer require backsystem/autocomplete
config/routes/autocomplete.yaml:
autocomplete:
resource: '@AutocompleteBundle/config/routes.yaml'
prefix: /api/search
src/Api/UserApi.php):
namespace App\Api;
use App\Entity\User;
use BackSystem\Autocomplete\AbstractApi;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
class UserApi extends AbstractApi {
public function getEntityClass(): string { return User::class; }
public function getUrl(): string { return '/users'; }
public function createFilteredQueryBuilder(EntityRepository $repository, string $query): QueryBuilder {
return $repository->createQueryBuilder('u')
->where('u.name LIKE :query')
->setParameter('query', '%'.$query.'%');
}
public function getValue($entity): string { return $entity->getId(); }
public function getLabel($entity): string { return $entity->getName(); }
}
src/Form/UserType.php):
use BackSystem\Autocomplete\Type\AutocompleteType;
$builder->add('user', AutocompleteType::class, [
'class' => UserApi::class,
'placeholder' => 'Search users...',
]);
Integrate autocomplete into a user selection field in a Symfony form (e.g., for assigning authors to blog posts). Test by typing in the field—results should appear dynamically.
API Layer:
AbstractApi for each entity type needing autocomplete.getEntityClass(): Return the entity class (e.g., User::class).createFilteredQueryBuilder(): Define search logic (e.g., LIKE queries).getValue()/getLabel(): Format displayed data (e.g., <b>ID</b> - Name).getTitle() for tooltip text (optional but improves UX).Form Integration:
EntityType with AutocompleteType.class (your API) and optional:
placeholder: User prompt.multiple: Allow multi-select (true).min_length: Minimum characters before search (default: 2).Frontend Handling:
autocomplete.html.twig if needed).prefix in autocomplete.yaml to group endpoints (e.g., /api/search/users).QueryBuilder results in createFilteredQueryBuilder() for large datasets.isValid() to enforce business rules (e.g., check user roles).AutocompleteType fields (e.g., author + editor).ActiveUserFilter) in createFilteredQueryBuilder().GET /api/search/users?q=john) with tools like Postman.LIKE queries are case-sensitive by default. Use LOWER() or ILIKE (PostgreSQL) for case-insensitive searches:
->where('LOWER(u.name) LIKE LOWER(:query)')
str_replace(' ', '', $query)). Adjust based on requirements (e.g., preserve partial matches).isValid() must return null for invalid IDs. Omit this method to skip validation./api/search doesn’t clash with existing routes. Use unique prefixes (e.g., /app/search)./api/search/{url}?q=test in your browser to verify raw data.$this->container->get('doctrine')->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
php bin/console cache:clear) if autocomplete fails to load.autocomplete.html.twig to modify the dropdown UI (e.g., add icons).AbstractApi to fetch data from external APIs (e.g., REST clients).createFilteredQueryBuilder() (e.g., ->andWhere('u.role = :role')).createFilteredQueryBuilder():
->setMaxResults(20)
user.department) in the same query to avoid lazy-loading issues.make:autocomplete (if available) to scaffold APIs.How can I help you explore Laravel packages today?