获取ManyToMany实体的关系


Get relation of ManyToMany entities

我一直在获取ManyToMany关系。我有两个实体OfferOfferType。我只在OfferEntity上定义了ManyToMany关系,在数据库中用多个OfferType保存优惠似乎很好——我看到了正确的联接表。

OfferEntity.php

/**
 * Offer Entity
 *
 * @ORM'Table(name="offer")
 * @ORM'Entity(repositoryClass="ProjectBundle'Repository'OfferRepository")
 */
class Offer
{
    /**
     * @Assert'Count(
     *      min = "1",
     *      minMessage = "You must specify at least one offer type."
     * )
     * @ORM'ManyToMany(targetEntity="OfferType")
     */
    private $types;
    public function __construct()
    {
        $this->types = new ArrayCollection();
    }
    /**
     * @return ArrayCollection
     */
    public function getTypes()
    {
        return $this->types;
    }
(...)

现在,我想将所有types分配给offer。我这样试过:

// $offer is an Entity
$query = $em->createQueryBuilder()
    ->select('offer.types')
    ->from('ProjectBundle:Offer', 'offer')
    ->where('offer = :offer')
    ->setParameters([
        'offer' => $offer
    ]);

不幸的是,我得到错误:

[2/2] QueryException: [Semantical Error] line 0, col 13 near 'types FROM ProjectBundle:Offer': Error: Invalid PathExpression. Must be a **StateFieldPathExpression**. 
[1/2] QueryException: SELECT offer.types FROM ProjectBundle:Offer offer WHERE offer = :offer

基于StackOverflow对类似问题的回答,尝试使用IDENTITY():

// $offer is an Entity
$query = $em->createQueryBuilder()
    ->select('IDENTITY(offer.types)')
    ->from('ProjectBundle:Offer', 'offer')
    ->where('offer = :offer')
    ->setParameters([
        'offer' => $offer
    ]);

但我有:

[2/2] QueryException: [Semantical Error] line 0, col 22 near 'types) FROM ProjectBundle:Offer': Error: Invalid PathExpression. Must be a SingleValuedAssociationField.
[1/2] QueryException: SELECT IDENTITY(offer.types) FROM ProjectBundle:Offer offer WHERE offer = :offer

我真的很感激任何关于建立ManyToMany关系的暗示,也许我的方法不正确?

您的方法不太正确。您需要加入要加载的实体。你应该多花点时间阅读关于实体关系的学说文档;querybuilder。

像这样。

$query = $em->createQueryBuilder()
    ->select('offer', 'types')
    ->from('ProjectBundle:Offer', 'offer')
    ->join('offer.types', 'types')
    ->where('offer = :offer')
    ->setParameters([
        'offer' => $offer
    ]);

然后您的结果将包含您想要的内容。

注意:您甚至没有加入类型以从优惠中获得类型,您也可以使用

$offer->getTypes() 

类型会以标准的教条方式懒惰加载。

但是按照上面的方式查询它会提前加载类型,这样可以避免延迟加载。这可能是一种更好的方法,也可能不是,具体取决于需求。

如果只在一侧设置多对多映射,则只能查询Offer,然后从中检索类型:

$builder = $em->createQueryBuilder()
    ->select('o', 't')
    ->from('ProjectBundle:Offer', 'o')
    ->join('o.types', 't')
    ->where('o.id = :offer')
    ->setParameter('offer', $offerId);
$offer = $builder->getQuery()->getOneOrNullResult();
$types = $offer->getTypes();

这是假设您只有$offerId可以使用。如果你已经有了完整的Offer实例,你也可以直接调用它的getTypes(),剩下的由条令来处理。

如果你要在OfferType实体上定义逆映射,比如:

class OfferType
{
    /**
     * @ORM'ManyToMany(targetEntity="Offer", mappedBy="types")
     */
    private $offers;
}

您可以只查询以下类型:

$builder = $em->createQueryBuilder()
    ->select('t')
    ->from('ProjectBundle:OfferType', 't')
    ->join('t.offers', 'o')
    ->where('o = :offer')
    ->setParameter('offer', $offer);
$types = $builder->getQuery()->getResult();