我正在使用 Symfony-2.1 和 Propel 开发一个基本的 CRUD 应用程序。理想情况下,我的模型将在推进 XML 模式中定义,并且 GUI 将自动更新以反映更改。我认为在我给定的时间限制内这是不可能的,但我正在努力尽可能接近。
我的第一个折衷方案是手动创建表单类型,因为推进表单类型生成器相当简陋。但是为了保持手动采用的水平(例如在添加新模型类型时),我想完全通过自定义表单类型的定义来解决以下问题:
我有一个中等复杂的 Title 模型,它与 TitleFragment 模型(代表历史出版物的主标题、副标题和短标题)具有一对多的关系。在我编辑标题的 HTML 表单中,我实现了标准的“添加一个”行为以允许添加另一个 TitleFragment(如symfony 食谱中所述)。
食谱解决方案为表单元素提出了一个列表结构,我添加了两个 JavaScript 指示器类来触发该表单元素上的 jQuery 控件元素生成代码:
<form [...]>
<ol class="collection-editor collection-sortable"
data-prototype="{{ form_widget(form.titleFragments.vars.prototype)|e }}">
{% for titleFragment in form.titleFragments %}
<li>
{{ form_widget(titleFragment) }}
</li>
{% endfor %}
</ol>
[...]
</form>
我想通过对自定义表单类型使用 symfony 表单主题技术来自动生成该标记。为了实现这一点,我继承了 symfony 集合表单类型,只是更改了它的名称以使我的自定义表单主题适用于该表单:
class SortableCollectionType extends \Symfony\Component\Form\Extension\Core\Type\CollectionType {
public function getName() {
return 'sortableCollection';
}
}
现在,我必须通过 sortableCollection_widget 块来增加默认的 symfony 表单主题(form_div_layout.html.twig),以强制将我的集合呈现为列表并将一些 JavaScript 指示符类附加到列表(如代码示例 #1 中)。
问题在于,在模板中,form.titleFragments 依赖于模型(并且将始终依赖于模型,因为数据需要绑定到 Title 模型的 TitleFragments 的底层集合)。
class TitleType extends BaseAbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('titleFragments', // no choice for a generic name here
new Form\DerivedType\SortableCollectionType(), array(
'type' => new TitlefragmentType(),
'allow_add' => true,
'by_reference' => false,
));
}
}
我考虑过将属性的名称(例如“titleFragments”)传递给模板,因为从 1.2 版开始,twig 支持对对象属性的动态访问(使用属性函数)。
有人知道如何从我的自定义表单类型一直获取数据到树枝模板吗?没关系,尽管它当然是多余的并且有点笨拙。
$builder->add('titleFragments',
new Form\DerivedType\SortableCollectionType(), array(
'type' => new TitlefragmentType(),
'options' => array('collectionPropertyName' => 'titleFragments'),
我没有发现表单构建器的 Symfony API特别有用。