You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony3 FOS User下UsersType注入EntityType表单提交类型错误如何解决

修复方案

方案1:使用数据转换器(推荐,适用中间表有自定义字段的场景)

如果你的UsersChannelBrand中间表除了关联用户和品牌外还有其他字段,用数据转换器做类型转换即可:

  1. 新建数据转换器类
// src/Bl/CoreBundle/Form/DataTransformer/ChannelBrandToUsersChannelBrandTransformer.php
namespace Bl\CoreBundle\Form\DataTransformer;

use Bl\CoreBundle\Entity\ChannelBrand;
use Bl\CoreBundle\Entity\UsersChannelBrand;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\DataTransformerInterface;

class ChannelBrandToUsersChannelBrandTransformer implements DataTransformerInterface
{
    private $em;
    private $currentUser;

    public function __construct(EntityManagerInterface $em, $currentUser)
    {
        $this->em = $em;
        $this->currentUser = $currentUser;
    }

    // 表单渲染:把UsersChannelBrand转换为ChannelBrand供前端选择展示
    public function transform($usersChannelBrands)
    {
        if (null === $usersChannelBrands) return new ArrayCollection();
        $channelBrands = new ArrayCollection();
        foreach ($usersChannelBrands as $ucb) {
            $channelBrands->add($ucb->getChannelbrand());
        }
        return $channelBrands;
    }

    // 表单提交:把选中的ChannelBrand转换为UsersChannelBrand关联实例
    public function reverseTransform($channelBrands)
    {
        $usersChannelBrands = new ArrayCollection();
        foreach ($channelBrands as $cb) {
            // 避免重复创建已有的关联
            $existing = $this->em->getRepository(UsersChannelBrand::class)
                ->findOneBy(['users' => $this->currentUser, 'channelbrand' => $cb]);
            if ($existing) {
                $usersChannelBrands->add($existing);
                continue;
            }
            // 创建新的关联实例
            $ucb = new UsersChannelBrand();
            $ucb->setUsers($this->currentUser);
            $ucb->setChannelbrand($cb);
            // 中间表有其他字段可在这里赋值
            $usersChannelBrands->add($ucb);
        }
        return $usersChannelBrands;
    }
}
  1. 修改UsersType注入EntityManager并绑定转换器
use Bl\CoreBundle\Form\DataTransformer\ChannelBrandToUsersChannelBrandTransformer;
use Doctrine\ORM\EntityManagerInterface;

class UsersType extends AbstractType
{
    private $em;

    // 注入EntityManager
    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('email', EmailType::class, array('label' => 'Email'))       
            ->add('username', TextType::class, array('label' => 'Usuario'))   
            ->add('name', TextType::class, array('label' => 'Nombre'))
            ->add('lastname', TextType::class, array('label' => 'Apellido'))
            ->add('roles', CollectionType::class, array('label' => 'Roles'))
            ->add('channelbrand_isolation', CheckboxType::class, array('label' => 'Aislado', 'required' => false))
            ->add('userschannelbrand', EntityType::class, array(
                'class' => 'Bl\CoreBundle\Entity\ChannelBrand',
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('cb')
                        ->where('cb.isActive =:active')->setParameter('active', true)
                        ->orderBy('cb.name', 'ASC');
                },
                'choice_label' => 'name',
                'multiple' => true,
                'label' => 'Canal',
                'required' => false,
                ))
            ->add('enabled', CheckboxType::class, array('label' => 'Activo', 'required' => false))
        ;

        // 给userschannelbrand字段绑定转换器
        $builder->get('userschannelbrand')
            ->addModelTransformer(new ChannelBrandToUsersChannelBrandTransformer(
                $this->em, 
                $options['data'] // 当前编辑的用户实例
            ));
    }
    // 剩余原有代码保持不变
}
  1. 把UsersType注册为服务(Symfony3.3+开启自动配置可省略)

方案2:直接改为多对多关联(适用中间表无额外字段的场景)

如果你的UsersChannelBrand中间表只有用户ID和品牌ID两个关联字段,没有其他自定义字段,可以直接把关联改为多对多,不需要中间实体,表单不用任何修改即可正常使用:

// 替换Users实体里原有userschannelbrand的关联注解
/**
 * @ORM\ManyToMany(targetEntity="Bl\CoreBundle\Entity\ChannelBrand")
 * @ORM\JoinTable(name="users_channel_brand", // 填写你原有中间表的表名
 *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="channel_brand_id", referencedColumnName="id")}
 * )
 */
protected $userschannelbrand;

改完执行php bin/console doctrine:schema:update --force更新数据库即可。


内容的提问来源于stack exchange,提问作者Luciano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 08:42:02