Php 具有默认值和嵌入表单的Symfony2实体

Php 具有默认值和嵌入表单的Symfony2实体,php,forms,symfony,Php,Forms,Symfony,我有一个类,它是一个表单类型(并嵌入到另一个表单中),用于选择commune、region和country,每个都有一个下拉列表(region取决于country)。我希望在构建国家/地区列表时默认选择某个国家/地区。这就是我所拥有的: $factory = $builder->getFormFactory(); $builder->add('pais', 'entity', array( 'class' => 'Codesin\ColegiosBundle\Localidad

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

$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;
    }
));

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

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

尝试在设置数据设置后数据表单事件:可以在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);

这可能有用。请尝试让我们知道进展情况

您需要插入此就绪捆绑包

并在此处进行配置


我使用这个框架来创建依赖表单

好吧,我想我终于明白了如何将它作为一种服务。你可能会问:“你为什么要提供这种服务?”?好吧,因为我需要将实体管理器注入到这个。我希望下面的教程有任何用处

自定义表单类型中的首选\u选项 假设您的数据库中保存了几个国家,它们是一个
国家
实体,在原则中正确定义。但是有一个问题-世界上有近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 为了搜索我们需要的实体,我们必须查询数据库。现在我们无法访问它,因为我们没有条令
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
,尤其是如果我们不是从控制器调用它,而是嵌入它?这里是魔术表演的地方

第三步:让它成为一种服务 为什么??因为这样我们可以向它注入
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 }
以下是一些注意事项:

  • 传递给服务的参数是另一个服务,即条令
    EntityManager
    。此参数传递给函数的构造函数,并从其他地方注入。这样,我们将确保始终有一个
    EntityManager
  • 在标记中,确保包含两个名为的标记。
    alias
    标记必须匹配自定义类型中从
    getName()
    返回的任何内容,在本例中为
    countrytype
如果您想了解更多关于依赖项注入和服务的信息,请访问此处:

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

步骤4:调用服务 这非常容易做到。还记得这句话吗

$builder->add('country', new CountryType());
现在将其更改为以下内容:

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

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

努力一点。应该有用。另外,如果您使用FF,请对页面进行完全刷新,因为它保存了旧的表单值。我声明了一个
new Pais()
,然后用它的值声明一个
setId()
。我在
首选选项中设置了它,但它就是不起作用。除非做其他事情?唯一的问题:我如何在表单中搜索?我是否使用
get
,如果是,我应该发送什么作为参数?您确定这在2.3上有效吗?我正在尝试使用它,显然它使用了不推荐的
字段
类型。。。我对源代码做了一点修改,结果弄得一团糟。我不得不修改了很多源代码,尽管如此,它还是不起作用