我试图找到一种简单的方法来使用实体表单类型,它使用连接表中的属性。我找到了一个解决方案,但我希望这可以比这更好地解决。
在我的情况下,我想在选择框中显示我的选项的翻译文本。遗憾的是,数据库已经存在于其翻译表中,因此我无法使用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一起使用。但我希望我遗漏了一些东西,并且有一个更好的解决方案来使用外国财产。