使用代表另一个字段 (`in`) 的值数组选择实体
Posted
技术标签:
【中文标题】使用代表另一个字段 (`in`) 的值数组选择实体【英文标题】:Select entities using an array of values that represents the another field (`in`) 【发布时间】:2022-01-22 18:31:23 【问题描述】:首先,对不起这个神秘的标题,但我真的不知道如何写一个更清楚。
这不是关于join
的问题,而是关于将in
与join
结合使用的问题。
我要说明我的情况。
我有一个array
,其中包含城市名称列表:
$cities = ['new_york', 'rome', 'hong_kong'];
这些城市位于cities
表中,每个城市都有自己的 ID:
------------------
| ID | slug |
| 1 | new_york |
| 2 | rome |
| 3 | hong_kong |
------------------
然后我有另一个表listings
,其中包含各种场地的列表。
每个Listing
都有一个字段city
,它将Listing
与它所在的City
相关联。
关系是ManyToOne
:
# Listing
/**
* @ORM\Entity(repositoryClass=ListingRepository::class)
* @ORM\Table(name="listings", schema="app")
*/
class Listing
/**
* @ORM\Id
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private int $id;
/** @ORM\Column(type="string", length=255, nullable=false) */
private string $name;
/** @ORM\ManyToOne(targetEntity=City::class, inversedBy="listings") */
private City $city;
...
然后
# City
/**
* @ORM\Entity(repositoryClass=CityRepository::class)
* @ORM\Table(name="cities", schema="app")
*/
class City
/**
* @ORM\Id
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private int $id;
/** @ORM\Column(type="string", length=255, nullable=false) */
private string $name;
/** @ORM\Column(type="string", length=255, nullable=false) */
private string $slug;
/** @ORM\OneToMany(targetEntity=Listing::class, mappedBy="city") */
private Collection $listings;
...
我想要达到的目标
传递 City
(ies) 的 slug 数组,我想选择属于每个传递的 City
的所有 Listing
s。
可能的解决方案
一种可能的解决方案是
-
首先按数组中的 slug 选择所有城市,
获取实体列表
City
并循环获取它们的 ID
将 ID 列表传递给 ListingRepository
并使用 in
类似这样的:
# Not tested, but it should work (may require some bug fixing)
...
/**
* @param City[] $cities
*
* @return Listing[]
*/
public function findAllByCities(array $cities):array
$qb = $this->createQueryBuilder('l');
$citiesIds = $this->getCitiesIds($cities);
return $qb
->select('l')
->where($qb->expr()->in('l.city', ':cities'))
->setParameter('cities', $citiesIds, Connection::PARAM_STR_ARRAY)
->getQuery()
->getResult();
/**
* @param City[] $cities
*
* @return int[]
*/
private function getCitiesIds(array $cities):array
return array_map(static fn(City $city): int => $city->getId(), $cities);
...
这种方法的缺点是:
-
我必须执行查询以获取城市列表
我必须循环每个返回的城市以获取其 ID
如果列表中的城市很多,这可能会变得很重。
问题
是否可以选择每个传递的 City
中的所有 Listing
s,但使用 slugs 而不是首先检索他们的 ID?
【问题讨论】:
【参考方案1】:您只需加入关联的表即可。
public function findAllByCities(array $cities):array
$qb = $this->createQueryBuilder('l');
return $qb
->select('l')
->join('l.city', 'c')
->where($qb->expr()->in('c.slug', ':cities'))
->setParameter('cities', $cities, Connection::PARAM_STR_ARRAY)
->getQuery()
->getResult();
【讨论】:
以上是关于使用代表另一个字段 (`in`) 的值数组选择实体的主要内容,如果未能解决你的问题,请参考以下文章