获取ManyToMany实体的关系

时间:2016-05-03 21:25:49

标签: php symfony doctrine-orm many-to-many

我坚持要获得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关系的任何提示,也许我对此的处理方法不正确?

2 个答案:

答案 0 :(得分:0)

你的方法不太对劲。您需要加入要加载的实体。你应该花更多的时间阅读关于实体关系的学说文档。 QueryBuilder的。

喜欢这样。

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

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

注意:您甚至 连接类型以从商品中获取类型,您也可以使用

$offer->getTypes() 

类型将以标准学说方式延迟加载。

但是如上所述查询它会提前加载类型 - 所以你要避免延迟加载。根据要求,这可能是也可能不是更好的方法。

答案 1 :(得分:0)

如果您只在一侧设置了多对多的映射,那么您将只能查询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();