检查 Symfony/Doctrine 中是否存在一对多的记录

Check not records exist for one to many in Symfony/Doctrine

我有一个一对多的关系。我有地图(每个街区都是单独的地图)和房间(每个地图都有多个房间)。所以对于实体(我会删除不需要的信息)我有:

/**
 * Block
 *
 * @ORM\Table(name="BLOCK")
 * @ORM\Entity
 */
class Block
{
    /**
     * @var integer
     *
     * @ORM\Column(name="PK", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="SEQ_GET_BLOCK_PK", allocationSize=1, initialValue=1)
     * @ORM\OneToMany(targetEntity="Rooms", mappedBy="blockId")
     */
    private $pk;
}

/**
 * Rooms
 *
 * @ORM\Table(name="ROOMS", indexes={@ORM\Index(name="IDX_EB2CE87E9B70DE02", columns={"MAP_ID"})})
 * @ORM\Entity
 */
class Rooms
{
    /**
     * @var integer
     *
     * @ORM\Column(name="PK", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="SEQ_GET_ROOMS_PK", allocationSize=1, initialValue=1)
     */
    private $pk;

    /**
     * @var \Block
     *
     * @ORM\ManyToOne(targetEntity="Block")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="BLOCK_ID", referencedColumnName="PK")
     * })
     */
    private $block;

现在要获取哪个块属于房间,很简单,在控制器中:

$roomRepo = $this->getDoctrine()->getRepository('AppBundle:Rooms');
$rooms = $roomRepo->findAll();

在 Twig 中(其中 fieldname 是块 table 中的另一个字段):

{% for room in rooms %}
    {{ room.block.fieldname }}
{% endfor %}

但是,显示方块列表并显示方块下方的房间变得更加困难。我希望能够获取块列表并在 Twig 中做一些事情,例如:

{% for block in blocks %}
    {% for room in block.rooms %}
        {{ room.name }}
    {% endfor %}
{% endfor %}

在这种情况下,我正在尝试获取其下没有任何房间的块列表。如果上述解决方案有效,我可以只计算每个街区的房间数,并且仅在有 none 时才显示。另一种选择是让查询在 createQueryBuilder 和 return 具有正确结果的实体块中进行计数。

有什么想法吗?我一直往下看这些路径,但过了一会儿就撞墙了。

您似乎需要一对多双向关系:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-many-bidirectional

Block中的$pk属性是主键吗?然后它不能有注释 @ORM\OneToMany 并且你应该有一个单独的 属性 和一组房间:

/** @OneToMany(targetEntity="Rooms", mappedBy="block") */
private $rooms;

然后 Room class:

/**
 * @ManyToOne(targetEntity="Block", inversedBy="rooms")
 * @JoinColumn(name="BLOCK_ID", referencedColumnName="PK")
 */
private $block;

您的用例似乎与文档中的用例完全相同,因此我建议您遵循他们的示例。

如果您可以使用 Martin 发布的解决方案,这是可行的方法,但是,就我而言,我决定添加一个更复杂的查询来获得我想要的结果。查询最终看起来像:

$blockRepo = $this->getDoctrine()->getRepository('AppBundle:Blocks');
$query = $blockRepo->createQueryBuilder('b')
    ->select('b')
    ->leftJoin("AppBundle:Rooms", "r", "WITH", "b.pk=r.block")
    ->where("b.location = :locationId")
    ->andWhere("r.pk IS NULL")
    ->setParameter("locationId", $locationId)
    ->getQuery();
$blocks = $query->getResult();

我实际上是在存储库中的自定义函数中执行此操作的,但这段代码应该可以工作。至于带有 locationId 的 2 行(where 和 setParameter),那只是因为我也想 select 另一个字段,如果省略这 2 行,它只会 select 全部没有房间的街区。