构建选择列表的最佳实践是什么?

时间:2012-12-28 09:03:00

标签: php symfony symfony-forms

我有一个带有选择类型元素的表单。我需要用数据填充它。据我所知,有3种方法。

1。控制器:

// Controller
public function myAction()
{
      $choices = ...; // create choices array
      $form = $this->createForm(new MyFormType($dm), null, array(
            'choices' => $choices,
        ));
}

// Form
class MyFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('cars', 'choice', array(
                'choices' => $options['choices']
        ));
    }
}

2。表单类+存储库

// Controller
public function myAction()
{
      $dm = $this->get('doctrine')->getManager();
      $form = $this->createForm(new MyFormType($dm));
}

// Form
class MyFormType extends AbstractType
{
    private $dm;

    public function __construct($dm) 
    {
        $this->dm = $dm;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('cars', 'choice', array(
                'choices' => $options['choices']
        ));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $list = array();
        foreach($this->dm->getRepository('MyBundle:Cars')->findAll() as $car) {
            $list[$car->getName()] = $car->getName();
        }

        $resolver->setDefaults(array(
            'choices'        => $list,
        ));
    }
}

第3。表单类+自定义服务

// Controller
public function myAction()
{
      $dm = $this->get('doctrine')->getManager();
      $form = $this->createForm(new MyFormType(), null, array(
            'myservice' => $this->get('myservice'),
        ));
}

// Form
class MyFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('cars', 'choice', array(
                'choices' => $options['myservice']->getCars()
        ));
    }
}

// Service
class MyService
{
    const ENTITY_CAR = 'MyBundle:Cars';

    /** @var DocumentManager */
    private $dm;

    public function __construct(DocumentManager $dm)
    {
        $this->dm = $dm;
    }

    public function getCars()
    {
        return $this->dm->getRepository("MyBundle:Cars")->findAll();
    }
}

我会表达自己的想法。

第一种选择不是最佳做法。特别是当涉及复杂的逻辑时。控制器应尽可能小。

第二个好多了。但它暴露了实体名称,如果我决定重命名它可能会出现问题。

第三是最好的选择,imho。实体名称集中在一个地方,更好的IDE类型提示,集中实体管理(搜索,保存,删除......)。主要缺点是可能过度设计的类,因为它负责许多读/写操作。另一方面,它可以分为几部分。

你怎么看?

2 个答案:

答案 0 :(得分:2)

如果你必须在你的代码中的其他地方重用该服务,那么第三种选择是好的(如果该服务与你所编写的服务相比会增长,我们稍后会看到它)。就这样,正如你所说,那个实体的“经理”就是一个,它包含了回购的名称,一个const等等。

BUT

如果此服务仅用作通过隐藏其名称来访问您的存储库的“推送器”,我认为此解决方案看起来仍然不太好。
显然,如果认为该服务具有多个持久性选项和多个检索选项(基于您选择的ORM),那么这可能是最佳实践。

在其他情况下,我认为第二个总是更好。

除非您想忽略所有良好做法,否则第一种情况不可行

答案 1 :(得分:1)

我建议使用第四个解决方案:使用entity字段,因为它被设计为一个选项字段,其中包含从DB加载的选项!

以下是官方文档http://symfony.com/doc/master/reference/forms/types/entity.html

以及如何使用它:

// Form
class MyFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('cars', 'entity', array(
            'class' => 'MyBundle:Cars',
            'property' => 'name',
            //Optionnal if you need to condition the selection
            'query_builder' => function(EntityRepository $er) {
                return $er->createQueryBuilder('u')->orderBy('u.username', 'ASC');
            },
        ));
    }
}