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

Symfony持久化对象到数据库报错:期望integer/null,传入User对象

解决表单提交时的类型错误:Expected argument of type "integer or null", "App\Entity\User" given

这个错误的核心原因很明确:你的表单里guru_id字段用了EntityType组件,它默认会返回完整的User实体对象,但你的Tag实体中guru_id属性定义的是integer类型,两者类型不匹配,导致Symfony在绑定表单数据时抛出类型错误。

下面提供两种解决方案,推荐第一种(符合Doctrine最佳实践),第二种适合你暂时不想修改实体结构的场景:


方案一:建立Doctrine实体关联(推荐)

如果guru_id本来就代表关联的用户,直接用实体关联关系更规范,也能避免类型问题:

1. 更新Tag实体

把原来的guru_id属性替换为ManyToOne关联:

// src/Entity/Tag.php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use App\Entity\User;

/**
 * @ORM\Entity(repositoryClass="App\Repository\TagRepository")
 */
class Tag {
    // ... 保留其他原有属性和方法 ...

    /**
     * @ORM\ManyToOne(targetEntity=User::class)
     * @ORM\JoinColumn(name="guru_id", referencedColumnName="id", nullable=true)
     */
    private $guru;

    // 新增关联的getter和setter
    public function getGuru(): ?User {
        return $this->guru;
    }

    public function setGuru(?User $guru): self {
        $this->guru = $guru;
        return $this;
    }

    // 可选:保留getGuruId方法方便快速获取ID
    public function getGuruId(): ?int {
        return $this->guru ? $this->guru->getId() : null;
    }
}

2. 更新AddType表单

将表单字段从guru_id改为对应关联属性guru:

// src/Form/Tag/AddType.php
use App\Entity\Tag;
use App\Entity\User;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AddType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('name', TextType::class)
            ->add('description', TextareaType::class)
            ->add('guru', EntityType::class, [
                'class' => User::class,
                'choice_label' => 'username',
                'required' => false // 允许不选择用户
            ]);
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults([
            'data_class' => Tag::class
        ]);
    }
}

3. 简化控制器代码

表单会自动绑定关联对象,不需要手动处理ID:

// src/Controller/Tag/AddController.php
public function add(Request $request) {
    $tag = new Tag();
    $form = $this->createForm(AddType::class, $tag);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $entityManager = $this->getDoctrine()->getManager();
        $tag->setApproved(false);
        $tag->setCreatedTs(new \DateTime());

        try {
            $entityManager->persist($tag);
            $entityManager->flush();
            $guruInfo = $tag->getGuru() ? $tag->getGuru()->getUsername() : 'no assigned guru';
            $this->addFlash('success', "Tag Submitted for review! {$guruInfo}");
        } catch (\Exception $e) {
            $this->addFlash('danger', 'Something went skew-if. Please try again.');
        }

        return $this->redirectToRoute('tag_add');
    }

    return $this->render('tag/add.html.twig', ['form' => $form->createView()]);
}

方案二:仅存储用户ID(不推荐,但适配当前实体结构)

如果只想存ID而不建立关联,可以修改表单让它直接返回用户ID:

修改AddType为ChoiceType

把EntityType换成ChoiceType,指定返回值为用户ID:

// src/Form/Tag/AddType.php
use App\Entity\User;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

// 记得让AddType继承AbstractController才能调用getDoctrine
class AddType extends AbstractController {
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $users = $this->getDoctrine()->getRepository(User::class)->findAll();
        
        $builder->add('name', TextType::class)
            ->add('description', TextareaType::class)
            ->add('guru_id', ChoiceType::class, [
                'choices' => $users,
                'choice_label' => 'username',
                'choice_value' => 'id', // 明确返回用户ID而非对象
                'required' => false
            ]);
    }

    // ... 保留configureOptions方法 ...
}

这样表单提交后,$tag->getGuruId()会直接得到整数ID,不需要额外处理,你的原有控制器代码可以继续使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:05:18