php - 具有默认值和嵌入形式的 Symfony2 实体

标签 php forms symfony

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

$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。在这种情况下,如何设置选定的默认值?

最佳答案

好吧,我想我终于明白了如何将其作为一项服务。 “你为什么要把它变成一项服务?”,你可能会问?好吧,因为我需要为此注入(inject)实体管理器。希望以下教程对您有所帮助。

自定义表单类型中的 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

根据您的选择,您会得到一个异常(exception)。出于某种奇怪的原因,这样做:

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

然后

'preferred_choices' => array($defaultCountry)

也不行。

这里是乐趣的开始。

第 2 步:添加 EntityManager

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

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 传递给它,尤其是当我们不是从 Controller 调用它而是嵌入它时?这是施展魔法的地方。

第 3 步:使其成为服务

为什么?因为这样我们可以向它注入(inject)一个 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。这个参数被传递给函数的构造函数并从其他地方注入(inject)。这样我们将确保我们始终有一个 EntityManager
  • 在标签中,确保包含两个已命名的标签。 alias 标记必须匹配从 getName() 返回的自定义类型中的任何内容,在本例中为 countrytype

如果您想了解更多有关依赖注入(inject)和服务的信息,请访问此处:Service Container.

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

第四步:调用服务

这非常容易做到。还记得这句话吗?

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

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

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

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

关于php - 具有默认值和嵌入形式的 Symfony2 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18628368/

相关文章:

symfony2 按属性对对象集合进行排序

javascript - 将 angularjs 表单提交到数据库

php - Symfony2 表格 : Show already uploaded files when form is invalid

forms - 一个 <input> 中的 HTTP multipart/form-data 多个文件

php - 登录时验证用户并授予他们有限的数据库权限

php - PostgreSQL 参数绑定(bind)与 JSONB 运算符冲突

php - 我可以使用 Google API 查找最近的城市吗?

javascript - 尝试在我的网络应用程序上使用 google plus 登录时,不断收到 "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup"

php - 多个div同步及时刷新

Symfony2 FosUserBundle 和 SonataUserBundle : overriding entities?