3

我有一个用于选择公社、地区和国家/地区的表单类型(并且反过来嵌入到另一种表单中)的类,每个都有一个下拉列表(地区取决于国家/地区)。我希望在构建国家列表时默认选择某个国家。这就是我所拥有的:

$factory = $builder->getFormFactory();
$builder->add('pais', 'entity', array(
'class' => 'Codesin\ColegiosBundle\Localidad\Pais',
'property' => 'nombre',
'query_builder' => function (EntityRepository $repositorio) {
    $qb = $repositorio->createQueryBuilder('pais')
        ->orderBy('pais.nombre');
        return $qb;
    }
));

我试过使用preferred_value(它说我需要一个对象,我无法从任何地方获取它,因为我在类中没有数据库访问权限)和data(它不起作用)。我尝试在这两种情况下都使用实体的 id。在这种情况下,如何设置选定的默认值?

4

4 回答 4

4

好吧,我想我终于明白如何将其作为服务了。“你为什么要把它变成一项服务?”,你可能会问?好吧,因为我需要为此注入实体管理器。我希望下面的教程有任何用处。

自定义表单类型中的 Preferred_choices

假设您的数据库中保存了几个国家,它们是一个Country实体,在 Doctrine 中正确定义。但有一个问题——全球有近 250 个国家,而用户最有可能来自一个国家!因此,假设您需要默认选择一个国家/地区,或者位于列表顶部。

第 1 步:填充字段

假设我们正在构建一个自定义表单类型,CountryType. 让我们定义它。

class CountryType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('country', 'entity', array(
             'class' => 'Acme\AcmeBundle\Locality\Country',
             'property' => 'name',
             'query_builder' => function (EntityRepository $repository) {
                 $qb = $repository->createQueryBuilder('country')->orderBy('country.name');
                 return $qb;
             }
        ));
    }

    public function getDefaultOptions(array $options)
    {
        return array('data_class' => 'Acme\AcmeBundle\Locality\Country');
    }

    public function getName()
    {
        return 'countrytype';
    }

}

当你从某个地方调用它时,例如,

$builder->add('country', new CountryType());

一切都很好,除了默认情况下您没有选择国家/地区。更糟糕的是,如果您尝试添加

'preferred_choices' => array(15) //Say, 15 is the id of the country

根据您的选择,您将获得例外。出于某种奇怪的原因,这样做:

$defaultCountry = new Country();
$defaultCountry->setId(15);

进而

'preferred_choices' => array($defaultCountry)

也不起作用。

这就是乐趣开始的地方。

第 2 步:添加 EntityManager

为了搜索我们需要的实体,我们必须查询数据库。现在我们无法访问它,因为我们没有 Doctrine EntityManager。我们要做的是向我们的类添加一个,将其作为参数传递给构造函数并将其存储为类的私有属性。

class CountryType extends AbstractType
{
    //Add this
    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('country', 'entity', array(
             'class' => 'Acme\AcmeBundle\Locality\Country',
             'property' => 'name',
             'query_builder' => function (EntityRepository $repository) {
                 $qb = $repository->createQueryBuilder('country')->orderBy('country.name');
                 return $qb;
             }
        ));
    }

    public function getDefaultOptions(array $options)
    {
        return array('data_class' => 'Acme\AcmeBundle\Locality\Country');
    }

    public function getName()
    {
        return 'countrytype';
    }

    //Add this
    private $em;
}

之后我们查询数据库。

class CountryType extends AbstractType
{
    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //Add the following lines
        $qb = $this->em->createQueryBuilder();
        $resultset = $qb->select('country')
                        ->from('Acme\AcmeBundle\Locality\Country', 'country')
                        ->where('country.id = ?1')
                        ->setParameter(1, 15)
                        ->getQuery()
                        ->execute();

        $default = $resultset[0];

        $builder->add('country', 'entity', array(
             'class' => 'Acme\AcmeBundle\Locality\Country',
             'property' => 'name',
             'preferred_choices' => array($default), //Add this too
             'query_builder' => function (EntityRepository $repository) {
                 $qb = $repository->createQueryBuilder('country')->orderBy('country.name');
                 return $qb;
             }
        ));
    }

    public function getDefaultOptions(array $options)
    {
        return array('data_class' => 'Acme\AcmeBundle\Locality\Country');
    }

    public function getName()
    {
        return 'countrytype';
    }

    private $em;
}

但是现在我们遇到了一个问题:我们不能再调用它了!!我们如何传递它一个EntityManager,特别是如果我们不是从控制器调用它而是嵌入它?这就是施展魔法的地方。

第 3 步:使其成为服务

为什么?因为这样我们可以EntityManager向它注入一个。转到Acme/AcmeBundle/Resources/cofig/services.yml并添加以下行:

acme.acmebundle.countrytype:
    class: Acme\AcmeBundle\Types\CountryType
    arguments: ["@doctrine.orm.entity_manager"]
    tags:
        - { name: form.type, alias: countrytype }

这里有一些注意事项:

  • 传递给服务的参数是另一个服务,即 Doctrine EntityManager。这个参数被传递给函数的构造函数并从其他地方注入。这样,我们将确保我们始终拥有一个EntityManager.
  • 在标签中,确保包含两个已命名的标签。该alias标记必须与getName()您的自定义类型中返回的任何内容相匹配,在本例中为countrytype.

如果您想了解更多关于依赖注入和服务的信息,请访问:服务容器。

现在,最大的问题是:我们如何称呼它?

第四步:调用服务

这非常容易做到。还记得这条线吗?

$builder->add('country', new CountryType());

现在将其更改为以下内容:

$builder->add('country', 'countrytype');

就是这样!现在,您的自定义类型附加了一个实体管理器,并且无需传递任何参数。祝你下一个项目好运!

于 2013-09-06T07:49:49.153 回答
0

如果您将表单类型与模型对象一起使用,请在对象本身上设置默认值。

于 2013-09-05T08:08:29.573 回答
0

尝试SET_DATAPOST_SET_DATA表单事件:您可以在 lambda 函数中执行以下操作:

$data = $event->getData();
$form = $event->getForm();

// search in the form for the right entity to set as country.. let's consider $country

$data->setCountry($country);
$event->setData($data);

它可能会起作用。尝试让我们知道进度

于 2013-09-05T08:30:30.993 回答
0

你需要插入这个准备好的包https://github.com/shtumi/ShtumiUsefulBundle

并在这里配置它https://github.com/shtumi/ShtumiUsefulBundle/blob/master/Resources/doc/dependent_filtered_entity.rst

我使用框架来制作依赖表格

于 2013-09-05T13:54:18.560 回答