acseo/select-autocomplete-bundle

轻松实现Symfony表单自动完成

安装: 1,502

依赖项: 0

建议者: 0

安全: 0

星星: 3

观察者: 4

分支: 1

开放问题: 0

类型:symfony-bundle

2.1 2021-01-21 23:31 UTC

This package is auto-updated.

Last update: 2024-09-22 07:31:31 UTC


README

Build Status

介绍

此捆绑包帮助您在symfony表单中构建自动完成字段,无需声明任何控制器或操作。

完全可配置,您可以非常容易地覆盖自动完成过程的任何部分。

默认支持Doctrine ORM & ODM,但您可以为其他扩展创建自己的提供者!

安装

使用composer安装源代码

$ composer require acseo/select-autocomplete-bundle

启用捆绑包

// config/bundles.php

return [
    Acseo\SelectAutocomplete\SelectAutocompleteBundle::class => ['all' => true]
];

全局(或局部在模板中)使用捆绑包表单主题

# config/packages/twig.yaml

twig:
    form_themes: 
        - '@SelectAutocomplete/form_theme.html.twig'

使用

让我们从一个简单的例子开始

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\User;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => User::class,
        // The searchable properties used for query
        'properties' => ['profile.firstName', 'profile.lastName'],
    ])
;

使用您最喜欢的js库,将渲染的输入转换为自动完成输入(以select2为例)

$('.acseo-select-autocomplete').each((i, el) => {
    const $el = $(el);

    $el.select2({
        minimumInputLength: 1,
        ajax: {
            cache: false,
            url: $el.data('autocomplete-url'),        // Get autocomplete url to retrieve search responses
            delay: 250,
            dataType: 'json',
            data: params => ({
                q: params.term || '',                  // Append the search terms to url
                // response_format: 'json'             // (optional, json by default, see form type options for allowed values) 
            }),
            processResults: data => ({                 // Transform entrypoint resuls
                results: Object.keys(data).map(value => ({
                    id: value,
                    text: data[value]
                }))
            })
        }
    });
});

请注意此js示例中的3个重要事项

  • 渲染的输入有一个data-autocomplete-url属性,其中的值可用于检索搜索结果。
  • 查询参数q,代表搜索词,必须添加到data-autocomplete-url的值中。
  • 默认情况下,搜索结果通过入口点返回,例如[{ "value": "label" }]

您的自动完成现在功能齐全!

表单选项

提示:您也可以通过创建一个扩展AutocompleteType的类来全局覆盖过程的任何部分。

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class
    ])
;

属性

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,
        'properties' => 'targetProperty',
        // OR
        'properties' => ['name', 'profile.email'],
    ])
;

显示

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,
        
        'display' => 'targetPropertyOrMethod',
        // OR
        'display' => 'nestedProperty.targetProperty',
        // OR
        'display' => ['user.firstName', 'user.lastName'],
        // OR 
        'display' => function(TargetClass $object): string {
            return $object->getTargetProperty();
        },
    ])
;

策略

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,
        
        'strategy' => 'starts_with', // LIKE ...%
        // OR
        'strategy' => 'ends_with',   // LIKE %...
        // OR
        'strategy' => 'contains',    // LIKE %...%
        // OR
        'strategy' => 'equals',      // = ...
    ])
;

多选

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,
        'multiple' => true,
    ])
;

格式

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;
use Symfony\Component\HttpFoundation\Response;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,
        
        // Options values are provided by your serializer (these are default format supported by symfony serializer)
        // Format can be override from js by add response_format param in data-autocomplete-url
        'format' => 'json', // xml|csv|yaml|...

        // OR

        // Encode response with your logic 
        'format' => function (array $normalized, Response $response): Response {
            return $response->setContent(json_encode($normalized));
        }
    ])
;

标识符

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,
        
        // Identifier is used as choice value 
        'identifier' => 'targetPropertyOrMethod',
    ])
;

autocomplete_url

有时您需要此选项来从特定入口点检索搜索结果。

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,
        
        // This option value will be set in data-autocomplete-url of select input attributes
        'autocomplete_url' => '/my-custom-entrypoint?param1=kevin',
    ])
;

转换器

use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,
        
        // Don't transform identifiers values to objects
        'transformer' => false,

        // OR

        // Use custom transformer
        'transformer' => $myCustomTransformer
    ])
;

提供者

use Acseo\SelectAutocomplete\DataProvider\Doctrine\AbstractDoctrineDataProvider;
use Acseo\SelectAutocomplete\Form\Type\AutocompleteType;
use App\Entity\TargetClass;

$formBuilder
    ->add('example', AutocompleteType::class, [
        'class' => TargetClass::class,

        // Override provider on search action to retrieve custom collection (Usage of partial query is allowed)
        // The second argument is the default provider which supports the model class
        'provider' => function(string $terms, AbstractDoctrineDataProvider $provider) {
            return $provider->getRepository(TargetClass::class)
                ->createQueryBuilder('o')
                ->where('o.name LIKE :name')
                ->setParameter('name', $terms.'%')
                ->getQuery()
                ->getResult()
            ;

            // You can also just override default query (available with ORM & ODM Doctrine providers)
            //
            // if ($provider instanceof ORMDataProvider) {
            //     $qb = $provider->createSearchQueryBuilder('o', TargetClass::class, ['name'], $terms, 'starts_with');
            //     // Custom query
            //     return $qb->getQuery()->getResult();
            // }
            //
            // if ($provider instanceof ODMDataProvider) {
            //     $qb = $provider->createSearchAggregationBuilder(TargetClass::class, ['name'], $terms, 'starts_with');
            //     // Custom query
            //     return $qb->execute()->toArray();
            // }
        },
        
        // OR
            
        // Use your own provider object
        'provider' => $myProvider,

        // OR

        // You can specify provider to use (the service has to be tagged as acseo_select_autocomplete.data_provider).
        // 2 providers are included by default : ORMDataProvider and ODMDataProvider.
        // You can add many providers, for specific model class or other kind of databases !
        'provider' => MyCustomProvider::class,
                
        // OR
        
        // Create custom provider
        // To know more about providers, please see Providers section.
        'provider' => [
            'find_by_ids' => function(array $ids, AbstractDoctrineDataProvider $provider) {
                return $provider->getRepository(TargetClass::class)->findBy(['id' => $ids]);
            },
            'find_by_terms' => function(string $terms, AbstractDoctrineDataProvider $provider) {
                return $provider->getRepository(TargetClass::class)
                    ->createQueryBuilder('o')
                    ->where('o.name LIKE :name')
                    ->setParameter('name', $terms.'%')
                    ->getQuery()
                    ->getResult()
                ;
            }
        ],
        
        // If provider option is not set, the provider used is the first which supports model class
    ])
;

提供者

提供者类用于从数据库检索搜索结果,并将表单视图数据转换为模型对象。

默认包含2个Doctrine提供者:ORMDataProvider和ODMDataProvider,支持多个数据库连接。

您可以为特定模型类或特定数据库创建自己的提供者。这是一个示例

<?php

namespace App\Form\Autocomplete\DataProvider;

use Acseo\SelectAutocomplete\DataProvider\DataProviderInterface;

class CustomDataProvider implements DataProviderInterface
{
    private $manager;

    public function __construct(\SomeWhere\CustomManager $manager)
    {
        $this->manager = $manager;
    }
    
    /**
     * Does provider supports the model class.
     */
    public function supports(string $class): bool
    {
        return $this->manager->supports($class);
        
        // To make specific provider for specific model class
        // return $class === \App\Entity\Foo::class
    }
    
    /**
     * Used to retrieve object with form view data (reverseTransform).
     */
    public function findByIds(string $class, string $identifier, array $ids): array
    {
        return $this->manager->findOneBy([ $identifier => $ids ]);
    }
    
    /**
     * Find collection results of autocomplete action.
     */
    public function findByTerms(string $class, array $properties, string $terms, string $strategy): array
    {
        $qb = $this->manager->createQuery($class);
        
        switch ($strategy) {
            case 'contains':
                $qb->contains($properties, $terms);
            break;
            
            // ... Rest of strategies code
        }
        
        return $qb->limit(20)->exec();
    }
}

最后,用acseo_select_autocomplete.data_provider标记此服务。

services:
    App\Form\Autocomplete\DataProvider\CustomDataProvider:
        autowire: true
        tags: ['acseo_select_autocomplete.data_provider']

现在,如果它支持给定的模型类,此提供者将默认调用。