【问题标题】:Symfony4 - How to update a doctrine ArrayCollection ?Symfony4 - 如何更新学说 ArrayCollection ?
【发布时间】:2018-12-27 22:24:36
【问题描述】:

我有一个我的实体成员是一个arrayCollection。使用经典的表单构建器可以正常工作,我可以选择多个项目并将其保留。但是当我尝试更新控制器中的对象时,出现错误:“调用数组上的成员函数 setFaavailability()”。

我的实体简历:

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\FaAvailability", 
   inversedBy="faavailability")
 * @ORM\JoinColumn(nullable=true)
 * @ORM\Column(type="array")
 */
 public $faavailability;

 /**
 * @return mixed
 */
public function getFaavailability()
{
    return $this->faavailability;
}

/**
 * @param mixed $faavailability
 */
public function setFaavailability($faavailability)
{
    $this->faavailability = $faavailability;
}

在我的控制器中:

 $varFaavailability = $animal->faperson->getFaavailability();
 foreach($varFaavailability as $availability){
         if($availability->getName() == $animal->typepet->getName()){
           $varFaavailability->removeElement($availability);
           $faPerson = $em->getRepository(FaPerson::class) >findById($animal->faperson->getId());
           $faPerson->setFaavailability($varFaavailability);
           $em->persist($faPerson);
           $em->flush();
         }
}

有什么想法吗?

【问题讨论】:

  • 尝试从 $faavailability 的注释中删除“@ORM\Column(type="array")”。
  • ManyToOne 关系,不返回 arrayCollection,只有 ManyToMany 或 oneToMany

标签: php symfony doctrine arraycollection


【解决方案1】:

如果我没记错的话,当您将字段设置为 ArrayCollection 时,这意味着您在两个实体之间具有 oneToMany 关系。 从您的代码中,我可以告诉您,您正试图将数据保存在错误的实体中。您通常在每个项目中添加 owning_entity_id(1-to-N) (1-to-N) 并将其持久化。在您的代码中,您试图一次设置所有引用,这永远不会发生。删除 setFaavailability() 或重新定义实体的关系。

你不应该尝试在一个super duper setter 函数中大量添加外键关系。循环浏览所有项目并设置对“父”实体的引用。

【讨论】:

    【解决方案2】:

    问题出在这部分:$faPerson = $em->getRepository(FaPerson::class)->findById($animal->faperson->getId());

    findBy* 方法将尝试查找多个实体并将它们返回到 Collection。 如果您正在寻找一个人,您可以改用findOneById。或者(假设 id 在 Doctrine 中被配置为标识符)你甚至可以使用 find 方法:$faPerson = $em->getRepository(FaPerson::class)->find($animal->faperson->getId());

    【讨论】:

    【解决方案3】:

    一些通用的cmets:

    1. 在 Doctrine 中,您永远不必使用 ID。使用实体 对象!例如,如果您从请求参数中获取 ID,则只需要 findById。
    2. 您应该重新考虑变量的命名,以明确它是一个集合 ($availabilities) 还是单个 ($availability)。
    3. 始终使用 getter/setter 方法而不是字段(typepet 与 getTypepet())。
    4. 在最后调用一次 flush() 以在一个事务中更新所有实体。

    我已按照我的理解重命名了以下变量。但是我仍然不确定 $animal->faperson->getFaavailabilities() 返回什么,因为一开始你想循环遍历结果,然后通过 setFaavailability() 将其设置为单个?

     //Should be a Doctrine ArrayCollection
     $varFaavailabilities = $animal->faperson->getFaavailabilities();
    
     foreach($varFaavailability as $availability){
             if($availability->getName() == $animal->getTypepet()->getName()) {
    
               //Why do you want to remove an element from the current loop?
               $varFaavailability->removeElement($availability);
    
               //No need to use Id
               $faPerson = $animal->getFaperson();
    
               //A single one?
               $faPerson->setFaavailability($availability);
    
               //More than one? addFaavailability should exist.
               $faPerson->addFaavailability($availability);
    
               $em->persist($faPerson);
    
             }
    }
    $em->flush();
    

    【讨论】:

    • 是的,你是对的,这段代码更好。当 if 条件为真时,我只想从 arrayCollection 中删除一个元素。如果我执行 $faPerson->setFaavailability($varFaavailability),则 Faavailability 属性不会持续存在。我更改为 $faPerson->setFaavailability($varFaavailability->removeElement($availability)) 它保持值'1'......这很奇怪。你有什么想法吗?
    • 只需调用 $varFaavailability->removeElement($availability);没有 setFaavailability()
    猜你喜欢
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多