检查 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 具有正确结果的实体块中进行计数。
有什么想法吗?我一直往下看这些路径,但过了一会儿就撞墙了。
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 全部没有房间的街区。
我有一个一对多的关系。我有地图(每个街区都是单独的地图)和房间(每个地图都有多个房间)。所以对于实体(我会删除不需要的信息)我有:
/**
* 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 具有正确结果的实体块中进行计数。
有什么想法吗?我一直往下看这些路径,但过了一会儿就撞墙了。
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 全部没有房间的街区。