Doctrine Symfony3编辑实体:主键缺少值时出错

Doctrine Symfony3编辑实体:主键缺少值时出错,doctrine,entity,primary-key,symfony,composite-key,Doctrine,Entity,Primary Key,Symfony,Composite Key,我尝试为产品目录创建树结构。 目录可以有多个级别,并且级别可以包含多个产品 我设法将我的结构保存在数据库中,但当我想编辑它时,出现以下错误: Error : Missing value for primary key catalogCode on AppBundle\Entity\CatalogLevel at OutOfBoundsException ::missingPrimaryKeyValue ('AppBundle\Entity\CatalogLevel', 'catalogCode'

我尝试为产品目录创建树结构。 目录可以有多个级别,并且级别可以包含多个产品

我设法将我的结构保存在数据库中,但当我想编辑它时,出现以下错误:

Error : Missing value for primary key catalogCode on AppBundle\Entity\CatalogLevel
at OutOfBoundsException ::missingPrimaryKeyValue ('AppBundle\Entity\CatalogLevel', 'catalogCode')
in vendor\doctrine\common\lib\Doctrine\Common\Proxy\AbstractProxyFactory.php at line 125
在CatalogController中执行此操作时:

$form = $this->createForm(CatalogTreeType::class, $catalog);
但是,就在那一行之前,我验证了我的水平是否正确,看起来情况就是这样:

// Create an ArrayCollection of the current levels
$originalLevels = new ArrayCollection();
foreach ($catalog->getLevels() as $level) {
   var_dump($level->getCatalogCode());
   $originalLevels->add($level);
}

// returns
AppBundle\Controller\CatalogController.php:337:string 'TT-FTEST' (length=8)

AppBundle\Controller\CatalogController.php:337:string 'TT-FTEST' (length=8)
CatalogLevel
实体有一个复合键:levelId+catalogCode

考虑到主键catalogCode不是空的,我不理解这个错误

目录实体

/**
 * @ORM\Table(name="catalogue")
 * @ORM\Entity(repositoryClass="AppBundle\Entity\CatalogRepository")
 * @UniqueEntity(fields="code", message="Catalog code already exists")
 */
class Catalog
{
    /**
     * @ORM\Column(name="Catalogue_Code", type="string", length=15)
     * @ORM\Id
     * @Assert\NotBlank()
     * @Assert\Length(max=15, maxMessage="The code is too long ({{ limit }} characters max)")
     */
    private $code;

    /**
     * @ORM\OneToMany(targetEntity="CatalogLevel", mappedBy="catalog", cascade={"persist", "remove"})
     * @Assert\Valid
     */
    private $levels;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->levels = new ArrayCollection();
    }

    /**
     * Get levels
     *
     * @return ArrayCollection
     */
    public function getLevels()
    {
      return $this->levels;
    }

    /**
     * Add level
     *
     * @param \AppBundle\Entity\CatalogLevel $level
     *
     * @return Catalog
     */
    public function addLevel(\AppBundle\Entity\CatalogLevel $level)
    {
        $level->setCatalogCode($this->getCode());
        $level->setCatalog($this);

        if (!$this->getLevels()->contains($level)) {
            $this->levels->add($level);
        }

        return $this;
    }

    /**
     * Remove level
     *
     * @param \AppBundle\Entity\CatalogLevel $level
     */
   public function removeLevel(\AppBundle\Entity\CatalogLevel $level)
    {
        $this->levels->removeElement($level);
    }
}
/**
 * @ORM\Table(name="catalogue_niveau")
 * @ORM\Entity(repositoryClass="AppBundle\Entity\CatalogLevelRepository")
 */
class CatalogLevel
{
    /**
     * @ORM\Column(name="Niveau_ID", type="string", length=15)
     * @ORM\Id
     */
    private $id;

    /**
     * @ORM\Column(name="Catalogue_Code", type="string", length=15)
     * @ORM\Id
     */
    private $catalogCode;

    /**
     * @ORM\ManyToOne(targetEntity="Catalog", inversedBy="levels")
     * @ORM\JoinColumn(name="Catalogue_Code", referencedColumnName="Catalogue_Code")
     */
    private $catalog;

    /**
     * Set id
     *
     * @param string $id
     *
     * @return CatalogLevel
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * Get id
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set catalogCode
     *
     * @param string $catalogCode
     *
     * @return CatalogLevel
     */
    public function setCatalogCode($catalogCode)
    {
        $this->catalogCode = $catalogCode;

        return $this;
    }

    /**
     * Get catalogCode
     *
     * @return string
     */
    public function getCatalogCode()
    {
        return $this->catalogCode;
    }
}
目录级实体

/**
 * @ORM\Table(name="catalogue")
 * @ORM\Entity(repositoryClass="AppBundle\Entity\CatalogRepository")
 * @UniqueEntity(fields="code", message="Catalog code already exists")
 */
class Catalog
{
    /**
     * @ORM\Column(name="Catalogue_Code", type="string", length=15)
     * @ORM\Id
     * @Assert\NotBlank()
     * @Assert\Length(max=15, maxMessage="The code is too long ({{ limit }} characters max)")
     */
    private $code;

    /**
     * @ORM\OneToMany(targetEntity="CatalogLevel", mappedBy="catalog", cascade={"persist", "remove"})
     * @Assert\Valid
     */
    private $levels;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->levels = new ArrayCollection();
    }

    /**
     * Get levels
     *
     * @return ArrayCollection
     */
    public function getLevels()
    {
      return $this->levels;
    }

    /**
     * Add level
     *
     * @param \AppBundle\Entity\CatalogLevel $level
     *
     * @return Catalog
     */
    public function addLevel(\AppBundle\Entity\CatalogLevel $level)
    {
        $level->setCatalogCode($this->getCode());
        $level->setCatalog($this);

        if (!$this->getLevels()->contains($level)) {
            $this->levels->add($level);
        }

        return $this;
    }

    /**
     * Remove level
     *
     * @param \AppBundle\Entity\CatalogLevel $level
     */
   public function removeLevel(\AppBundle\Entity\CatalogLevel $level)
    {
        $this->levels->removeElement($level);
    }
}
/**
 * @ORM\Table(name="catalogue_niveau")
 * @ORM\Entity(repositoryClass="AppBundle\Entity\CatalogLevelRepository")
 */
class CatalogLevel
{
    /**
     * @ORM\Column(name="Niveau_ID", type="string", length=15)
     * @ORM\Id
     */
    private $id;

    /**
     * @ORM\Column(name="Catalogue_Code", type="string", length=15)
     * @ORM\Id
     */
    private $catalogCode;

    /**
     * @ORM\ManyToOne(targetEntity="Catalog", inversedBy="levels")
     * @ORM\JoinColumn(name="Catalogue_Code", referencedColumnName="Catalogue_Code")
     */
    private $catalog;

    /**
     * Set id
     *
     * @param string $id
     *
     * @return CatalogLevel
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * Get id
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set catalogCode
     *
     * @param string $catalogCode
     *
     * @return CatalogLevel
     */
    public function setCatalogCode($catalogCode)
    {
        $this->catalogCode = $catalogCode;

        return $this;
    }

    /**
     * Get catalogCode
     *
     * @return string
     */
    public function getCatalogCode()
    {
        return $this->catalogCode;
    }
}
我想提醒您,当我显示预先填写的表单时,editAction(它在addAction上工作得非常好)上发生了此错误


谢谢你的帮助

我认为这是因为您在实体目录级别没有自动递增id。尝试将id添加到此代码:

@ORM\GeneratedValue(strategy="AUTO")

在创建实体的方式上存在一些问题。您应该使用自动生成策略。此外,“@ORM\Id”注释是唯一标识符

此外,您的“JoinColumn”不正确。您需要重新引用“Catalog”实体及其id(标识符)。类CatalogLevel中不需要2个“@ORM\Id”条目

因此,进行以下更改:

/**
 * @ORM\Table(name="catalog")
 * @ORM\Entity(repositoryClass="AppBundle\Entity\CatalogRepository")
 */
class Catalog
{
    /**
     * @ORM\Column(name="cat_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $cat_id;

    /**
     * @ORM\OneToMany(targetEntity="CatalogLevel", mappedBy="catalog", cascade={"persist", "remove"})
     * @Assert\Valid
     */
    private $levels;
     ...


/**
 * @ORM\Table(name="catalog_level")
 * @ORM\Entity(repositoryClass="AppBundle\Entity\CatalogLevelRepository")
 */
class CatalogLevel
{
    /**
     * @ORM\Column(name="cat_level_id", type="integer")
     * @ORM\Id
      * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $cat_level_id;

    /**
     * @ORM\ManyToOne(targetEntity="Catalog", inversedBy="levels")
     * @ORM\JoinColumn(name="local_cat_id", referencedColumnName="cat_id")
     */
    private $catalog;
     ...

感谢您的回复,但我不使用CatalogLevel的自动增量id,因为我使用jquery创建树,并在提交后使用表单数据修复id。例如,级别id如下所示:项目1、项目2、项目xx。save-in数据库运行良好。我所有的等级数据都在我的“目录”表中。此外,我的错误发生在AbstractProxyFactory类上,而不是直接发生在实体CatalogLevel上。好的,所以我不知道是什么原因造成的,但有一种更简单的方法可以做到这一点。你可以用。所有的魔法都在一张桌子上。我不知道,谢谢!我会看看它是否与我的结构相对应。谢谢你的回复,但我不会对Catalog和CatalogLevel使用自动递增id。用户可以输入目录的代码,该代码用作主键。为了获得级别的唯一标识符,我使用了一个由目录代码和提交表单后获得的级别id组成的复合键(我在jquery中构建了一个拖放树,id在js中生成)。save-in数据库运行良好。我所有的等级数据都在我的“目录”表中。此外,我的错误发生在AbstractProxyFactory类上,而不是直接发生在实体CatalogLevel上。我在internet上找到了避免此错误的方法:删除实体CatalogLevel中$catalogCode属性的@ORM\Id。编辑表单正在显示,并且已预先填充级别数据。但我认为这不是一个可行的解决方案。。。