我有一个表单来创建文档。一方面,我可以添加名称和说明,然后我可以选择创建的文档所属的一个或多个代理。 每个代理商都被分配到一个特定的市场(共有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;
}
我认为这可能有助于消除我的副本,但它没有......任何想法为什么?
答案 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
。
Document
与ManyToMany
有Agency
的关系。
然后在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更为合理。