主义许多关系

时间:2016-05-14 03:17:55

标签: php doctrine-orm zend-framework2

很简单(我想!),我有一个Invoice实体和一个Coupon实体。发票可以有许多优惠券适用于他们。相反,优惠券可用于许多发票。

排除getter / setter:

发票

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(完美)的连接表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();

我收到此错误:

  

通过关系\ Application \ Entity \ Invoice#coupons找到了一个新实体,该优惠券未配置为级联实体的持久操作:(coupon toString)。要解决此问题:在此未知实体上显式调用EntityManager#persist()或在映射中配置级联持久保存此关联,例如@ManyToOne(..,cascade = {\ u0022persist \ u0022})。

现在,我不希望这个创建新的优惠券;为什么要这样做呢?优惠券已经存在,它是从ER加载的,它正被添加到现有实体中。

如果我执行了错误消息所说的内容,它会尝试将新优惠券复制到优惠券表中。

感谢您的建议。

1 个答案:

答案 0 :(得分:2)

Doctrine\ORM\EntityManager::update()似乎不存在。你不应该在addCoupon()调用和flush()调用之间做任何事情。

如果简化代码并没有神奇地修复它,那么下一步应该是确保$couponMapper->getEntityManager() === $invoiceMapper->getEntityManager()

您不清楚如何实例化这些映射器类,但了解每个EntityManager为实体维护自己的内部标识映射非常重要。因此,如果您的DIC由于某种原因实例化两个不同的EM(每个Mapper一个),则$ invoiceMapper的EM不会将$ coupon识别为管理实体。

情况确实如此。假设您正在使用ZF2的ServiceManager,您必须明确设置您的EntityManger服务不被共享。

但考虑到你提供的代码,不知何故有两个不同的EntityManagers是我能想到的最明显的事情。