Symfony3编辑实体:错误主键缺失值

问题描述:

我尝试为产品目录创建树结构。 一个目录可以有多个级别,并且级别可以包含多个产品。Symfony3编辑实体:错误主键缺失值

我设法救我的结构,数据库,但是当我想编辑它,我有这样的错误:

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); 
    } 
} 

CatalogLevel实体

/** 
* @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; 
    } 
} 

我会喜欢e提醒你,当我显示预先填充的表单时,editAction发生了这个错误(它在addAction上工作得很好)。

感谢您的帮助!

我认为这是因为您在实体CatalogLevel中没有自动增加id。尝试将此代码添加至此代码:

@ORM\GeneratedValue(strategy="AUTO") 
+0

感谢您的答复,但因为我创造我的树与jQuery和我修复表单数据IDS提交后,我不使用CatalogLevel自动增量ID。例如,关卡ID是这样的:item-1,item-2,item-xx。 保存在数据库中效果很好。我的“catalogue_niveau”表中包含所有关卡数据。此外,我的错误发生在AbstractProxyFactory类上,而不是直接在Entity CatalogLevel上。 – Felurian

+0

好的,所以我不知道可能是什么原因造成的,但是有一种更简单的方法。你可以使用[doctrine tree extension](https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/tree.md#including-extension)。一张桌子上的所有魔法。 – ciurciurek

+0

我不知道,谢谢!我会看看它是否与我的结构相符。 – Felurian

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

此外,您的“JoinColumn”不正确。您需要回顾“目录”实体,它是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; 
    ... 
+0

感谢您的回复,但我没有为Catalog和CatalogLevel使用自动增量ID。用户可以输入目录的代码,并将此代码用作主键。 为了具有唯一的级别标识符,我使用组合键与目录代码和级别ID,我在提交表单后(我在jquery中构建拖放树并在js中生成ids)后获得了该级别ID。 保存在数据库中效果很好。我的“catalogue_niveau”表中包含所有关卡数据。此外,我的错误发生在AbstractProxyFactory类上,而不是直接在Entity CatalogLevel上。 – Felurian

+0

我在互联网上找到了一种避免此错误的方法:删除实体CatalogLevel中的$ catalogCode属性的@ORM \ Id。 编辑窗体正在显示,并预先填充了关卡数据。但我不认为这是一个可行的解决方案... – Felurian