【问题标题】:Doctrine select many from the one (many-to-one unidirectional (different bundles))Doctrine select many from the one(多对一单向(不同捆绑))
【发布时间】:2017-06-13 09:39:11
【问题描述】:

处理限制可用选项的遗留项目使我处于需要解决以下问题的情况,理想情况下是教义。

我在不同的捆绑包中有两个实体,它们具有单向多对一链接。

BundleA 依赖于 BundleB,实体链接如下:

BundleA/Entity/TheMany:

/**
 * @var TheOne $theOne
 * @ORM\ManyToOne(targetEntity="BundleB\Entity\TheOne")
 * @ORM\JoinColumn(name="theone_id", referencedColumnName="id", onDelete="SET NULL")
 * 
 */
private $theOne;

现在我需要从 BundleB 中选择所有 TheOne 实体,并且对于每个实体,我都需要所有 TheMany 实体。

查询还需要可根据 TheOne 实体的任何属性或相关 TheMany 实体的计数进行排序。

在 Doctrine 中构建一个查询来返回所有 TheOne 实体和一个 TheMany 是相当简单的......但是我很难想出一个 Doctrine 查询来返回所有相关的 TheMany 实体而不仅仅是一个。

我希望有人可能遇到过类似的问题并因此有所了解?

这可能解释得不够清楚,请指导我进一步解释。

【问题讨论】:

    标签: symfony doctrine-orm dql many-to-one


    【解决方案1】:

    最后,我能够通过使用 GROUP_CONCAT(需要包含 https://github.com/beberlei/DoctrineExtensions)来实现我所需要的。

    查询看起来像这样:

        $queryBuilder->select(
            'to,
            GROUP_CONCAT(DISTINCT tm.id SEPARATOR \',\') as theManyIds, 
            COUNT(DISTINCT tm.id) as HIDDEN theManyCount'
        )
            ->from('BundleB\Entity\TheOne', 'to')
            ->leftJoin(
                'BundleA\Entity\TheMany',
                'tm',
                Join::WITH,
                'to.id = tm.theOne'
            )
            ->groupBy('to.id')
            ->orderBy($sortString, $direction)
            ->setFirstResult($start)
            ->setMaxResults($limit);
    

    我接受了链接这两个捆绑包的后果来妥协 - 但是通过使用本机 SQL 和结果集映射 (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html) 可以避免这种情况。

    【讨论】:

      【解决方案2】:

      所以你要做的是得到所有的,并为每一个找到所有的许多。但是您想将所有这些都放在一个数组中,或者您想为实体创建一个数组数组? (我在这里做了什么)

      $em = $this->getDoctrine()->getManager();
      $theones = $em->getRepository('BundleA:theOne')
          ->createQueryBuilder('p')
          ->OrderBy(//your ordering)
          ->getQuery()
          ->getArrayResult()
      
      $theManies = [];
      
      for($theones as $theOne){
          $theManies [] = $em->getRepository('BunbleB:theMany')
              ->createQueryBuilder('p')
              ->Where('p.theOne = :theOne')
              ->setParameter('theOne', $theOne)
              ->getQuery()
              ->getArrayResult();
           $finalOnes[$theOne->getId()] = sizeof($theManies)
      }
      
      asort($finalOnes);
      return array_keys($finalOnes);
      

      【讨论】:

      • 类似的东西,但是这种方法有两个问题,第一个是我需要按与任何给定 TheOne 实体相关联的“TheMany”实体的数量对 TheOne 列表进行排序。另一个问题是 BundleA 没有 BundleB 的可见性。我不能介绍这个链接,因为它是一个循环依赖。 BundleA 需要 BundleB 但 BundleB 不需要 BundleA (由于作曲家之类的循环依赖问题,我无法将其添加为要求)。实际上这两个捆绑包是相互依赖的,应该合并,但由于各种原因我不能这样做。
      • 另一点是,如果我得到实际的水合 TheMany 实体,对于这个任务的目的来说并不重要,我实际上只需要一个逗号分隔的 ID 列表。我觉得我可能不得不求助于 SQL 而不是 DQL。
      • 好的,首先,如果我得到你的要求,我会更改代码,所以你会得到一个 TheOne 订单列表,按它们链接到的数量列出
      • 但我不明白为什么 BundleB 不应该被识别。如果你只是添加use Path\of\BundleB; 这应该可以工作。
      • BundleB 不能作为 BundleA 的要求包含在内,因为 BundleB 已经是 BundleA 的要求。我不能引入循环依赖,而且在这两个包之间添加耦合是不好的做法(尽管如上所述它们应该是同一个包)。在应用程序中这不是问题,因为这两个包在实践中总是存在的,但是对于自动化测试,每个包必须能够作为独立包(加上任何依赖项)通过它的全套测试。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-31
      • 1970-01-01
      • 1970-01-01
      • 2022-12-01
      • 1970-01-01
      相关资源
      最近更新 更多