Symfony 7+EasyAdmin 4表单提交:如何将数组转为ProjectPosition对象?
问题:提交表单时如何将数组转换为ProjectPosition对象避免类型错误?
我使用Symfony 7搭配EasyAdmin 4,因技术需求通过Ajax动态加载现有ProjectPosition的选项到表单选择字段。提交表单时,系统尝试将选中选项的数组写入期望为ProjectPosition对象的字段,从而引发错误。
错误提示
Expected argument of type "?App\Entity\ProjectPosition", "array" given at property path "projectPosition".
相关代码
自定义ProjectPositionsField(Form/Field/ProjectPositionsField.php)
public static function new(string $propertyName, ?string $label = null) { return (new self()) ->setProperty($propertyName) // (= projectPosition) ->setLabel('') ->setFormType(ProjectPositionsType::class) ->setDefaultColumns('col-md-4 col-xxl-3') ->setFormTypeOptions([ 'attr' => [ 'class' => 'activity_projectPositions', 'name' => 'Activity[projectPosition]', ] ]); } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'mapped' => false, ]); }
自定义ProjectPositionsType(Form/Field/ProjectPositionsType.php)
public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->add('projectPosition', EntityType::class, [ 'class' => ProjectPosition::class, 'choice_label' => 'description', 'multiple' => false, 'expanded' => false, 'placeholder' => 'Select a position', 'choices' => [], 'allow_extra_fields' => true, ]); } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => null, ]); }
动态加载选项的JS代码
success: function(data) { data.forEach(function(position) { projectPositionDropdown.append('<option value="' + position.id + '">' + position.task + '</option>'); }); $("#Activity_projectPosition").show(); },
解决方案
问题出在你嵌套了表单字段:ProjectPositionsType内部又定义了一层projectPosition字段,导致提交时的数据结构是['projectPosition' => 选中ID]的数组,而非直接的ID值,无法被Symfony自动转换为ProjectPosition对象。
方式一:简化表单结构(推荐)
直接在ProjectPositionsField中使用EntityType,去掉多余的ProjectPositionsType嵌套:
// Form/Field/ProjectPositionsField.php public static function new(string $propertyName, ?string $label = null) { return (new self()) ->setProperty($propertyName) ->setLabel('') ->setFormType(EntityType::class) // 直接使用EntityType ->setDefaultColumns('col-md-4 col-xxl-3') ->setFormTypeOptions([ 'class' => ProjectPosition::class, 'choice_label' => 'description', 'multiple' => false, 'expanded' => false, 'placeholder' => 'Select a position', 'choices' => [], // 留空由Ajax填充 'attr' => [ 'class' => 'activity_projectPositions', 'name' => 'Activity[projectPosition]', ] ]); } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'mapped' => true, // 开启映射,让表单自动处理对象转换 ]); }
之后删除ProjectPositionsType类即可。
方式二:调整嵌套字段的配置
如果必须保留ProjectPositionsType,修改配置让它直接返回选中值,而非嵌套数组:
// Form/Field/ProjectPositionsType.php public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->add('projectPosition', EntityType::class, [ 'class' => ProjectPosition::class, 'choice_label' => 'description', 'multiple' => false, 'expanded' => false, 'placeholder' => 'Select a position', 'choices' => [], 'compound' => false, // 关键设置:取消字段的嵌套结构 ]); } // 同时修改ProjectPositionsField的映射配置 public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'mapped' => true, // 开启映射 ]); }
两种方式都能让Symfony正确接收选中的ID,并自动转换为ProjectPosition对象,解决类型错误问题。
内容的提问来源于stack exchange,提问作者Christian Stegemann
相关产品推荐
相关产品推荐

