Doctrine 多对多关系
Doctrine ManyToMany Relationship
非常简单(我认为!),我有一个 Invoice 实体和一个 Coupon 实体。发票可以应用许多优惠券。优惠券反之,可用于多张发票。
排除getters/setters:
发票
namespace Application\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="invoices")
*/
class Invoice
/**
* @ORM\ManyToMany(targetEntity="Application\Entity\Coupon")
* @ORM\JoinTable(name="invoices_coupons")
*/
protected $coupons;
public function addCoupon( Coupon $coupon ){
if( !$this->coupons )
$this->coupons = new ArrayCollection();
$this->coupons->add($coupon);
}
}
优惠券
/**
* @ORM\Entity
* @ORM\Table(name="coupons", indexes={@ORM\Index(name="code_idx", columns={"code"})})
*/
class Coupon implements CandidateInterface
{
/**
* @var \Ramsey\Uuid\Uuid
*
* @ORM\Id
* @ORM\Column(type="uuid")
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
*/
protected $id;
/**
* @var string
* @ORM\Column(type="string", length=32, unique=true)
*/
protected $code;
}
当我 运行 帮助工具生成模式时,正如预期的那样,它创建了一个包含 coupon_id、invoice_id 的连接 table invoices_coupons (完美)。
所以在代码中,我有一个现有的存储发票和一个类似的现有优惠券。
看来我做不到:
// runs a QB to return the coupon, returns a Coupon Entity
$coupon = $couponMapper->getActiveByCode('SAVEBIG');
$invoice->addCoupon( $coupon );
$invoiceMapper->getEntityManager()->update( $invoice );
$invoiceMapper->getEntityManager()->flush();
我收到这个错误:
A new entity was found through the relationship \Application\Entity\Invoice#coupons that was not configured to cascade persist operations for entity: (coupon toString). To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={\u0022persist\u0022}).
现在,我不想创建新的优惠券;为什么要尝试这个?优惠券已存在,它是从 ER 加载的,正在添加到现有实体。
如果我按照错误消息所说的进行操作,它会尝试将新优惠券复制到优惠券 table。
感谢您的建议。
Doctrine\ORM\EntityManager::update()
似乎并不存在。您不必在 addCoupon() 调用和 flush() 调用之间执行任何操作。
如果简化您的代码并不能神奇地解决问题,您的下一步应该是确保 $couponMapper->getEntityManager() === $invoiceMapper->getEntityManager()
.
不清楚您是如何实例化这些映射器的 类,但重要的是要了解每个 EntityManager 都为实体维护自己的内部标识映射。因此,如果您的 DIC 出于某种原因正在实例化两个不同的 EM(每个 Mapper 一个),那么 $invoiceMapper 的 EM 不会将 $coupon 识别为托管实体。
如果是这样的话就很奇怪了。假设您正在使用 ZF2 的 ServiceManager,您必须明确地将 EntityManger 服务设置为不共享。
但是考虑到您提供的代码,我能想到的最明显的事情是拥有两个不同的 EntityManagers。
非常简单(我认为!),我有一个 Invoice 实体和一个 Coupon 实体。发票可以应用许多优惠券。优惠券反之,可用于多张发票。
排除getters/setters:
发票
namespace Application\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="invoices")
*/
class Invoice
/**
* @ORM\ManyToMany(targetEntity="Application\Entity\Coupon")
* @ORM\JoinTable(name="invoices_coupons")
*/
protected $coupons;
public function addCoupon( Coupon $coupon ){
if( !$this->coupons )
$this->coupons = new ArrayCollection();
$this->coupons->add($coupon);
}
}
优惠券
/**
* @ORM\Entity
* @ORM\Table(name="coupons", indexes={@ORM\Index(name="code_idx", columns={"code"})})
*/
class Coupon implements CandidateInterface
{
/**
* @var \Ramsey\Uuid\Uuid
*
* @ORM\Id
* @ORM\Column(type="uuid")
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
*/
protected $id;
/**
* @var string
* @ORM\Column(type="string", length=32, unique=true)
*/
protected $code;
}
当我 运行 帮助工具生成模式时,正如预期的那样,它创建了一个包含 coupon_id、invoice_id 的连接 table invoices_coupons (完美)。
所以在代码中,我有一个现有的存储发票和一个类似的现有优惠券。
看来我做不到:
// runs a QB to return the coupon, returns a Coupon Entity
$coupon = $couponMapper->getActiveByCode('SAVEBIG');
$invoice->addCoupon( $coupon );
$invoiceMapper->getEntityManager()->update( $invoice );
$invoiceMapper->getEntityManager()->flush();
我收到这个错误:
A new entity was found through the relationship \Application\Entity\Invoice#coupons that was not configured to cascade persist operations for entity: (coupon toString). To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={\u0022persist\u0022}).
现在,我不想创建新的优惠券;为什么要尝试这个?优惠券已存在,它是从 ER 加载的,正在添加到现有实体。
如果我按照错误消息所说的进行操作,它会尝试将新优惠券复制到优惠券 table。
感谢您的建议。
Doctrine\ORM\EntityManager::update()
似乎并不存在。您不必在 addCoupon() 调用和 flush() 调用之间执行任何操作。
如果简化您的代码并不能神奇地解决问题,您的下一步应该是确保 $couponMapper->getEntityManager() === $invoiceMapper->getEntityManager()
.
不清楚您是如何实例化这些映射器的 类,但重要的是要了解每个 EntityManager 都为实体维护自己的内部标识映射。因此,如果您的 DIC 出于某种原因正在实例化两个不同的 EM(每个 Mapper 一个),那么 $invoiceMapper 的 EM 不会将 $coupon 识别为托管实体。
如果是这样的话就很奇怪了。假设您正在使用 ZF2 的 ServiceManager,您必须明确地将 EntityManger 服务设置为不共享。
但是考虑到您提供的代码,我能想到的最明显的事情是拥有两个不同的 EntityManagers。