原则2 - 间接的一对多关联



经过大量寻找间接关联,我只提出了这个问题。我想知道的是与这个问题完全相反的,所以我正在建立它。给定相同的实体:

class Continent {
/**
* @ORMId
* @ORMColumn(type="integer", name="id")
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORMOneToMany(targetEntity="AppBundleEntityCountry", mappedBy="continent")
*/
private $countries;
}

class Country {
/**
* @ORMId
* @ORMColumn(type="integer", name="id")
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORMManyToOne(targetEntity="AppBundleEntityContinent", inversedBy="countries")
* @ORMJoinColumn(name="continent_id", referencedColumnName="id")
*/
private $continent;
/**
* @ORMOneToMany(targetEntity="AppBundleEntityCity", mappedBy="country")
*/
private $cities;
}
class City {
/**
* @ORMId
* @ORMColumn(type="integer", name="id")
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORMManyToOne(targetEntity="AppBundleEntityCountry", inversedBy="cities")
* @ORMJoinColumn(name="country_id", referencedColumnName="id")
*/
private $country;
}

有没有办法拥有一个大陆上所有城市的集合,而不必每次都构建自定义查询,其字段与国家/地区集合的方式相同,可能通过注释或动态映射?

我能想到的唯一方法是覆盖存储库中的find...方法——我不确定我究竟如何实现添加字段——然后循环遍历国家/地区并将其城市添加到新集合中,或者完全使用自定义查询。

首先是关于你的映射的评论。您的映射在这里是错误的:

inversedBy="countries"不是inversedBy="country",您可能想要一个名为continent_id而不是continentt_id的列

/**
* @ORMManyToOne(targetEntity="AppBundleEntityContinent", inversedBy="countries")
* @ORMJoinColumn(name="continent_id", referencedColumnName="id")
*/
private $continent;

在这里应该inversedBy="cities"而不是inversedBy="city"

/**
* @ORMManyToOne(targetEntity="AppBundleEntityCountry", inversedBy="cities")
* @ORMJoinColumn(name="country_id", referencedColumnName="id")
*/
private $country;

考虑对您的实体模型使用验证,原则 ORM 附带的验证工具将帮助您正确处理这些内容。


您可以通过内部连接具有某个大陆的国家/地区来获得这样的结果集。

在您的CityRepository

use DoctrineORMQueryExprJoin;
//...
public function findCitiesByContinent($params){
$queryBuilder = $this->createQueryBuilder('c')
->innerJoin('c.country', 'cc', Join::WITH, 'cc.continent = :continent')
->setParameter('continent', $params['continent']);
$query = $queryBuilder->getQuery();
return $query->getResult();
}

您可以重复使用查询,并在每次需要不同大陆的城市时将不同的大陆值传递给$params数组。

这段代码没有经过测试,但我认为它应该可以工作。如果您在测试时遇到问题,请发表评论。


您还可以添加@Edwin建议的方法,但您必须意识到它会急切地加载所有实体。如果您的表中有大量行(很多城市和国家(,这对性能来说是致命的。这就是为什么存储库中的查询会更好。


或者,您可以使用条件和集合筛选在实体内执行此操作。您可以在文档第 8.8 章中阅读有关如何执行此操作的信息。筛选集合

文档中也很好地解释了使用过滤器的优点:

如果尚未从数据库加载集合,则筛选 API 可以在 SQL 级别工作,以优化对大型集合的访问。

最新更新