在Symfony实体表单类型中使用外部属性

时间:2014-07-30 09:18:02

标签: symfony symfony-forms

我试图找到一种简单的方法来使用实体表单类型,它使用连接表中的属性。我找到了一个解决方案,但我希望这可以比这更好地解决。

在我的情况下,我想在选择框中显示我的选项的翻译文本。遗憾的是,数据库已经存在于其翻译表中,因此我无法使用symfony国家/地区表单类型。所以,例如,我有这些表:

        Country
+----+-------------+
| id | name        |
+----+-------------+
|  1 | Netherlands |
|  2 | Germany     |
+----+-------------+


        CountryTranslation
+----+-------------+------------+-----------+
| id | language_id | country_id | text      |
+----+-------------+------------+-----------+
|  1 |           1 |          1 | Nederland |
|  2 |           1 |          2 | Duitsland |
|  3 |           2 |          1 | ...       |
+----+-------------+------------+-----------+

        Flags
+----+------------+-----------------------------+
| id | country_id | img_url                     |
+----+------------+-----------------------------+
|  1 |          1 | http://flags.cdn.com/nl.gif |
+----+------------+-----------------------------+

现在在我的CMT中,我希望用户能够管理标志表。 CMT是多语言的,因此它应该以他自己的语言显示各国。所以在我的formbuilder中我想做这样的事情:

$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
    $flag = $event->getData();
    $form = $event->getForm();

    if (!$flag) {
        $form
            ->add('language', 'entity', array(
                'class' => 'MbDbLookupBundle:Country',
                'query_builder' => function(EntityRepository $er) {
                    return $er->createQueryBuilder('c')
                        ->innerJoin('c.countryTranslations', 'ct', 'WITH', 'ct.languageId = :languageId')
                        ->leftJoin('MyCmtBundle:Flag', 'f', 'WITH', 'f.country = c')
                        ->where('f.country IS NULL')
                        ->setParameter('languageId', $this->lang)
                    },
                'property' => 'ct.text', // <--------- This will not work
                'label' => 'Language',
                'position' => array('before' => 'title'),
            ));
    }
}

我尝试过的事情

  • 使用&#39;选择&#39;带Data Transformer as explained here的字段。起初这似乎没问题,但我无法在dynamic form as explained here中使用它。这是因为在addEventListener中,我可以使用$form->add,但由于创建函数不存在于该对象上,所以我无法使用$form->add(form->create(...))

  • 创建自定义表单类型。在我的应用程序中,我希望仅在尚未选择的国家/地区填充选择框。所以我需要加入我的&#34; Flags&#34;表也​​是,这就是我使用动态表单的原因。因此我无法使用自定义表单类型,因为我需要基于底层数据查询是动态的。

我的解决方案

在我的国家/地区实体中,我添加了函数getNameTranslated($langId=null)。当数组中只有一条记录时,它将返回此记录。这样我就可以使用内部联接查询对象,确保我已经在Country对象中有正确的翻译。为了使这个函数不那么肮脏,还可以选择通过使用参数手动获取区域设置。所以我想出了类似的东西:

public function getNameTranslated($langId=null) {
    if (!isset($langId) && count($this->nameTranslations) > 1)
        throw new \Exception('No locale given '.count($this->nameTranslations));

    foreach($this->nameTranslations as $nameTranslation) {
        if (!isset($langId) || ($nameTranslation->getLanguageId() == $langId))
            return $nameTranslation;
    }

    return false;
}

现在我可以在表单构建器中使用'property' => 'nameTranslated',也可以在表单事件监听器中使用。{/ p>

不知怎的,我仍然不喜欢这个解决方案。我宁愿在我的表单中解决问题,而不是在对象内部。

我认为,使用此表单活动会让我感到困惑的是,我正在加入我的&#34; Flags&#34;用于排除已选择语言的表格。否则我认为最好的选择是选择&#39;选择&#39;字段与Data Transformer一起使用。但我希望我遗漏了一些东西,并且有一个更好的解决方案来使用外国财产。

0 个答案:

没有答案