Symfony在pre persist上向对象添加数据

时间:2017-08-31 14:09:23

标签: symfony doctrine persist

我有一个表单来创建文档。一方面,我可以添加名称和说明,然后我可以选择创建的文档所属的一个或多个代理。 每个代理商都被分配到一个特定的市场(共有7个市场,因此一个市场可以有多个代理商,但一个代理商只属于一个市场!) 我想要实现的是一个" prePersist"功能可自动将正确的市场(取决于所选代理商的数量)添加到文档中。

我的文档实体拥有两个实体(市场和代理商)以及相关的getter和setter:

get_es_name_complete(self)

我知道我可以将prePersist函数添加到我的文档实体并尝试编写我想要实现的内容,但我不认为这样做是因为我需要这样的东西:

 /**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Market", inversedBy="uploadProfiles", cascade={"persist"})
* @ORM\JoinTable(name="document_uploadprofile_markets",
*   joinColumns={@ORM\JoinColumn(name="uploadprofile_id", referencedColumnName="id")},
*   inverseJoinColumns={@ORM\JoinColumn(name="market_id", referencedColumnName="id")})
**/
private $markets;

        /**
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Agency", inversedBy="uploadProfiles", cascade={"persist"})
         * @ORM\JoinTable(name="document_uploadprofile_agencies",
         *   joinColumns={@ORM\JoinColumn(name="uploadprofile_id", referencedColumnName="id")},
         *   inverseJoinColumns={@ORM\JoinColumn(name="iata8", referencedColumnName="iata8")})
         **/
        private $agencies;
  public function __construct()
    {
        $this->agencies = new \Doctrine\Common\Collections\ArrayCollection();
    $this->markets = new \Doctrine\Common\Collections\ArrayCollection();

}

       /**
 * Add market
 *
 * @param \AppBundle\Entity\Market $market
 *
 * @return UploadProfile
 */
public function addMarket(\AppBundle\Entity\Market $market)
{
    $this->markets[] = $market;

    return $this;
}

/**
 * Remove market
 *
 * @param \AppBundle\Entity\Market $market
 */
public function removeMarket(\AppBundle\Entity\Market $market)
{
    $this->markets->removeElement($market);
}

/**
 * Get markets
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getMarkets()
{
    return $this->markets;
}
  /**
     * Add agency
     *
     * @param \AppBundle\Entity\Agency $agency
     *
     * @return UploadProfile
     */
    public function addAgency(\AppBundle\Entity\Agency $agency)
    {
        $this->agencies[] = $agency;

        return $this;
    }

    /**
     * Remove agency
     *
     * @param \AppBundle\Entity\Agency $agency
     */
    public function removeAgency(\AppBundle\Entity\Agency $agency)
    {
        $this->agencies->removeElement($agency);
    }

    /**
     * Get agencies
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getAgencies()
    {
        return $this->agencies;
    }

我甚至不确定foreach循环是否正确,因为(到目前为止)结果始终为null。我已经在这里问了一个关于该主题的问题:Symfony use setter for Arraycollection in CreateController

我还尝试编写一个自己的存储库功能,以便从我的代理机构实体中获取所有不同的市场,但到目前为止还没有工作。

另一个想法是我的表单类中的POST_SUBMIT事件监听器,但到目前为止对我来说也没有意义。

有什么想法吗?如果需要更多代码,请告诉我们!

修改 我编辑并更改了上面的代码,以便在我的市场和文档之间建立多种关系。我接下来尝试的是,将prePersist函数添加到我的文档实体中它实际上工作正常但仍然具有OneToMany关系(它只是总是覆盖以前的市场,但现在不重要) 我现在正在尝试编辑该功能,以便可以将多个市场添加到文档中。 我有两个想法,但它们都没有成功:

  foreach($document->getAgencies() as $agency) {
      $document->setMarket($em->getRepository('AppBundle:Agency')->getMarket($agency));
     }

- >市场永远是空的

if(count($this->getAgencies()) > 0){
      foreach($this->getAgencies() as $agency) {
        $this->addMarket($agency->getMarket());
      }
}

更新

这是我的文档实体中的prepersist函数,然后是其中一条注释中建议的getMarkets()函数。 我将名称更改为addMarkets而不是getMarkets

if(count($this->getAgencies()) > 0){
      $upId = rtrim($this->getId(),"_up");
      $query = $em->createQuery("SELECT DISTINCT (a.market) FROM UserBundle\Entity\User u JOIN u.agencies a WHERE u.id = $userId");
      $marketIds = $query->getResult();

      $em = $this->getDoctrine ()->getManager ();
      $repository = $this->getDoctrine()
      ->getRepository('AppBundle:Market');
      $markets = $repository->findOneById($marketIds);
      $this->addMarket($markets);
    }
  }

另一种方法

所以我再次编辑它,现在我的功能看起来像

/**
    * @ORM\PrePersist
    */
    public function prePersist() {
if(count($this->getAgencies()) > 0){
      foreach($this->getAgencies() as $agency) {
        $this->addMarkets($agency->getMarket());
      }
    }
  }

public function addMarkets(\AppBundle\Entity\Market $market)
  {
      $markets = array();
      foreach($this->agencies as $agency) {
          $market = $agency->getMarket();
          $id     = $market->getId();

          // Skip duplicates
          if (isset($markets['id'])) {
              continue;
          }

          $markets[$id] = $market;
      }

      return $markets;
  }

我认为这可能有助于消除我的副本,但它没有......任何想法为什么?

3 个答案:

答案 0 :(得分:1)

这是逻辑上的结构错误。线索在你的问题和代码中。

  

自动添加正确的市场( s

        /**
        * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Market")
        * @ORM\JoinColumn(name="market", referencedColumnName="id")
        * @var \AppBundle\Entity\Market
        **/
        private $market;

不兼容。

如果一份文件可以有很多代理商,代理商可以拥有一个市场,那么您的文件必须允许许多市场。例如:

DocumentA has Agency1 and Agency2. 

Agency1 has MarketParis.

Agency2 has MarketMarrakesh.

这必然意味着DocumentA拥有(Agency1' s)MarketParis和(Agency2' s)MarketMarrakesh--许多市场。

您提出的问题是一个比设置或获取更大的主题。如果每个文档只需要一个市场,那么您必须在文档代理商之间强制执行唯一性。例如:

Your form creates DocumentA.

The user tries to set Agency1 (MarketParis) and Agency2 (MarketMarrakesh).
This throws an error because there can be ONLY ONE market.

或另一个例子:

Your form creates DocumentA

The user tries to set Agency1 (MarketParis) and Agency3 (MarketParis). 
This is successful because the uniqueness of the Document's Market is enforced. 

这有很多策略,比你的问题要大得多。

修改

如果您的基数逻辑是正确的(修复我上面描述的任何问题),并且您的学说注释包括所有实体中的级联持久性,从上面的代码看起来是正确的。我能想到的唯一不能正常工作的是" by_reference"你的表格的属性。设置" by_reference"在您的表单中false,在您的实体中设置了cascade-persist,应该保留与该表单关联的所有实体。请在此处查看by_reference文档:http://symfony.com/doc/current/reference/forms/types/collection.html#by-reference

答案 1 :(得分:1)

如果我理解你说的正确,我相信Documents根本不应该提到Markets。但只能引用Agency

DocumentManyToManyAgency的关系。

然后在Document中,您可以执行以下操作:

public function getMarkets()
{
    $markets = array();
    foreach($this->agencies as $agency) {
        $market = $agency->getMarket();
        $id     = $market->getId();

        // Skip duplicates
        if (isset($markets[id]) {
            continue;
        }

        $markets[$id] = $market;
    }

    return $markets;
}

答案 2 :(得分:0)

这看起来像错误的做法。在市场和代理商之间建立一个ToMany关系,在代理商和文件之间建立oneToMany更为合理。