2016-07-27 113 views
1

我实现了一个让管理员从表单中配置一些额外行为(实际上是Symfony Services)的系统。此刻我正在使用EntityType,以便让管理员从数据库中的表中选择一个或多个服务。在Symfony ChoiceType中显示带标签的服务

$builder->add('services', EntityType::class, array(
'class' => 'AppBundle:Services', 
'multiple' => true, 
)); 

但因为我在注册服务的Symfony本身我只是想,应该有办法从容器(或类似)获得的服务,创造一个新的ServiceTagType所以我不“T不得不增加他们在data baseservices.yml都和我可以这样做:

$builder->add('services', ServiceTagType::class, array(
'tag' => 'some.service.tag', 
'multiple' => true, 
)); 

在这里读,有我发现,你可以标签服务,但你当容器正在编译时,只能得到标记的服务列表 ...我努力寻找解决方法,但它一直没有用。

+2

在你的编译过程,你可以在你的ServiceTagType注入标记的业务和使用ServiceTagType作为服务在你的表格 – bourvill

回答

2

首先,你必须创建ServiceTagType(我假定这将延长ChoiceType而不是的EntityType):

如何创建一个自定义类型的记录here

// src/AppBundle/Form/Type/ServiceTagType.php 
namespace AppBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\OptionsResolver\OptionsResolver; 
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; 

class ServiceTagType extends AbstractType 
{ 
    private $tags; 

    public function setTags($tags) 
    { 
     $this->tags = $tags; 
    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'choices' => $this->tags 
     )); 
    } 

    public function getParent() 
    { 
     return ChoiceType::class; 
    } 
} 

注册您的ServiceTagType服务(因为你需要提供标签与setter injection

# services.yml 
app.form_type.service_tag: 
    class: AppBundle\Form\Type\ServiceTagType 
    tags: 
     - { name: form.type } 

然后,Bourvill建议,你可以收集你的标签在Compiler pass

use Symfony\Component\DependencyInjection\ContainerBuilder; 
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 
use Symfony\Component\DependencyInjection\Reference; 

class TagsCompilerPass implements CompilerPassInterface 
{ 
    public function process(ContainerBuilder $container) 
    { 
     if (!$container->has('app.form_type.service_tag')) { 
      return; 
     } 

     $definition = $container->findDefinition(
      'app.form_type.service_tag' 
     ); 

     $taggedServicesIds = array_keys($container->findTaggedServiceIds(
      'app.tagged_for_service_tag_type' 
     )); 

     $taggedServices = array_fill_keys($taggedServicesIds ,$taggedServicesIds); 

     $definition->addMethodCall('setTags',$taggedServices); 
    } 
} 

而且不要忘了register this Compiler pass

要在FullStack框架注册CompilerPass:

class AppBundle extends Bundle 
{ 
    public function build(ContainerBuilder $container) 
    { 
     parent::build($container); 

     $container->addCompilerPass(new TagsCompilerPass()); 
    } 
} 
+0

Upvote for a great answer @Alsatian! –

+0

哇!很好,完整答案,非常感谢。 – Astaroth