Symfony实现动态添加表单输入并存储JSON类型exception字段求助
解决Symfony中动态添加JSON类型异常字段的问题
我来帮你搞定这个动态添加异常项并存为JSON的问题,按照下面的步骤一步步来就行:
1. 创建异常项的子表单类型
首先,我们需要为单个异常项创建一个子表单,因为每个异常包含名称、日期、时间这些字段。新建App\Form\ExceptionItemType:
<?php namespace App\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\DateType; use Symfony\Component\Form\Extension\Core\Type\TimeType; class ExceptionItemType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name', TextType::class, [ 'label' => '异常名称' ]) ->add('startDate', DateType::class, [ 'label' => '开始日期', 'widget' => 'single_text' // 用单文本框选择日期,更友好 ]) ->add('endDate', DateType::class, [ 'label' => '结束日期', 'widget' => 'single_text' ]) ->add('startTime', TimeType::class, [ 'label' => '开始时间', 'widget' => 'single_text' ]) ->add('endTime', TimeType::class, [ 'label' => '结束时间', 'widget' => 'single_text' ]); } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'template' => 'form/exception_item_type.html.twig' // 后面会自定义这个模板 ]); } }
2. 更新主表单类TypeParkingType
把原来的exception字段改成CollectionType,这样Symfony就能处理一组异常项:
<?php namespace App\Form; use App\Entity\TypeParking; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TimeType; use Symfony\Component\Form\Extension\Core\Type\DateType; class TypeParkingType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('libelle', TextType::class) ->add('tempsmax', TimeType::class, [ 'widget' => 'single_text' ]) ->add('jourdebut', DateType::class, [ 'widget' => 'single_text' ]) ->add('jourfin', DateType::class, [ 'widget' => 'single_text' ]) ->add('heurstravail') // 如果这个字段也是类似结构,也可以用同样的CollectionType处理 ->add('exception', CollectionType::class, [ 'entry_type' => ExceptionItemType::class, 'allow_add' => true, // 允许添加新项 'allow_delete' => true, // 允许删除项 'by_reference' => false, // 必须设为false,因为我们要修改数组 'label' => '异常设置', 'prototype' => true, // 启用表单原型,用于动态复制 'prototype_name' => '__exception_index__', // 占位符,后面JS会替换 'attr' => [ 'class' => 'exception-collection' // 给容器加个类,方便JS定位 ] ]); } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => TypeParking::class, ]); } }
3. 自定义异常项的Twig模板
创建templates/form/exception_item_type.html.twig,美化每个异常项的布局,还加个删除按钮:
<div class="form-row mb-3"> <div class="col-md-2"> {{ form_label(form.name) }} {{ form_widget(form.name) }} {{ form_errors(form.name) }} </div> <div class="col-md-2"> {{ form_label(form.startDate) }} {{ form_widget(form.startDate) }} {{ form_errors(form.startDate) }} </div> <div class="col-md-2"> {{ form_label(form.endDate) }} {{ form_widget(form.endDate) }} {{ form_errors(form.endDate) }} </div> <div class="col-md-2"> {{ form_label(form.startTime) }} {{ form_widget(form.startTime) }} {{ form_errors(form.startTime) }} </div> <div class="col-md-2"> {{ form_label(form.endTime) }} {{ form_widget(form.endTime) }} {{ form_errors(form.endTime) }} </div> <div class="col-md-2 d-flex align-items-end"> <button type="button" class="btn btn-danger btn-remove-exception">删除</button> </div> </div>
4. 更新实体类的exception字段
推荐把json_array改成json(Symfony 3.4+支持,更贴合数据库JSON字段),还要确保有正确的getter和setter:
class TypeParking { // ... 其他字段 /** * @ORM\Column(type="json", nullable=true) */ private $exception = []; // 初始化为空数组,避免null问题 // ... 其他getter/setter public function getException(): ?array { return $this->exception; } public function setException(?array $exception): self { $this->exception = $exception; return $this; } }
5. 修改Twig表单模板(new.html.twig)
添加动态添加按钮和JS代码,实现点击“+”新增异常项:
{% extends 'base.html.twig' %} {% block body %} <h1>创建新停车类型</h1> {{ form_start(form) }} {{ form_widget(form) }} <!-- 添加异常项的按钮 --> <button type="button" id="add-exception" class="btn btn-success mt-3">+ 添加异常</button> <div class="mt-3"> <button type="submit" class="btn btn-primary">保存</button> </div> {{ form_end(form) }} <!-- 隐藏的表单原型,用于动态复制 --> {% set exception_prototype = form.exception.vars.prototype %} <div id="exception-prototype" class="d-none"> {{ form_widget(exception_prototype) }} </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $(document).ready(function() { const $collectionHolder = $('.exception-collection'); const $prototype = $('#exception-prototype').html(); // 初始索引值为现有异常项的数量 let index = $collectionHolder.find('.form-row').length; // 点击按钮添加新异常项 $('#add-exception').click(function() { // 替换原型中的占位符,确保每个表单字段的name属性唯一 const newForm = $prototype.replace(/__exception_index__/g, index); $collectionHolder.append(newForm); index++; }); // 点击删除按钮移除对应的异常项 $collectionHolder.on('click', '.btn-remove-exception', function() { $(this).closest('.form-row').remove(); }); }); </script> {% endblock %}
最后测试一下
现在你启动Symfony服务器,访问/new页面,就能看到“添加异常”按钮了,点击它会动态生成一组输入项,填写后提交表单,数据库里的exception字段就会存储成你想要的JSON格式啦!
内容的提问来源于stack exchange,提问作者Hyperion
相关产品推荐
相关产品推荐

