gpt4 book ai didi

php - 在 MySQL 树中搜索具有多对多关联的项

转载 作者:行者123 更新时间:2023-11-30 00:28:24 25 4
gpt4 key购买 nike

我们使用 Doctrine 2 进行数据库访问 tree extension .

第一个表是树形表,其中包含由此创建的欧盟位置 source

位置表:

id
name
parent
lft
rgt
lvl
root
companies

还有一个公司表,其中包含与位置表具有多对多关系的公司列表。这些地点是给定公司开展事件的地点。它可以是国家(0 级)、某个地区(1、2、3、4 级)或只是某个城市、城镇或村庄(5 级)。

公司表:

id
name
locations

我们有一个针对可以选择位置的公司的搜索表单。

现在我需要创建 DQL,它将选择给定位置(嵌套)的所有国家/地区。

因此,当我选择例如整个国家/地区时,它应该选择该国家/地区的所有公司、该国家/地区的地区以及该国家/地区的城市或城镇。

谢谢。

编辑:

我将父位置的“自动添加”(可能是临时的)添加到公司中。它只会遍历所有 parent 并添加它们。因此,当公司在城市进行事件并且用户选择整个国家或地区时,就会显示该公司。

不幸的是,仍然存在一个问题。如果某个公司在全国范围内开展业务,并且用户选择该国家/地区的城市,则不会显示该公司。

最佳答案

搜索并不是那么昂贵,人们只会在一次搜索查询中搜索几个位置。

所以我做的第一件事就是加载所有搜索到的位置的 ID 及其所有 parent 的 ID。

获取 parent 的 ID: BaseTreeFacade::getPathIds

public function getPathIds($entity)
{
$ids = $this->getPathQueryBuilder($entity)
->select('node.id')
->getQuery()
->getResult(AbstractQuery::HYDRATE_SCALAR);

return array_map('current', $ids);
}

此方法返回带有 id 的简单数组。现在我必须将搜索查询中的 id 与 parent 的 id 结合起来。

扩展 id: Helpers::expandTreeValues

public static function expandTreeValues(BaseTreeFacade $facade, array $values)
{
$result = [];

foreach ($values as $id) {
$entity = $facade->findOneById($id);

$result[] = [$id];
$result[] = $facade->getPathIds($entity);
}

$result = call_user_func_array('array_merge', $result);
$result = array_unique($result, SORT_NUMERIC);

return $result;
}

下一步是创建 where 子句来搜索位置及其子项。

创建 where 子句: Helpers::prepareWhereClauseForChildren

public static function prepareWhereClauseForChildren(BaseTreeFacade $facade, array $values)
{
$where = [];
$parameters = [];

foreach ($values as $id) {
$entity = $facade->findOneById($id);

$where[] = "(l.lvl > :level$id AND l.id > :left$id AND l.id < :right$id)";

$parameters["left$id"] = $entity->lft;
$parameters["right$id"] = $entity->rgt;
$parameters["level$id"] = $entity->lvl;
}

$where = implode(' OR ', $where);

return (object) [
'where' => $where === '' ? null : $where,
'parameters' => count($parameters) === 0 ? null : $parameters,
];
}

由于树的左右分支,我可以在所有子位置中搜索。最后一步是使用上一步中创建的 where 子句更新原始 QueryBuilder

完成 QueryBuilder: Helpers::updateWithTreeEntity

public static function updateWithTreeEntity(QueryBuilder $qb, array $values, $addWhere = null, array $addParameters = null)
{
if ($addParameters === null) {
$addParameters = [];
}

$addParameters['locations'] = $values;
$appendQuery = $addWhere === null ? '' : " OR $addWhere";

$qb->andWhere("l.id IN (:locations)$appendQuery");

foreach ($addParameters as $key => $value) {
$qb->setParameter($key, $value);
}
}

使用示例:

public function createQueryBuilderForSearchingInLocations(array $locations)
{
$gb = $this->createQueryBuilderSomehow();
$facade = $this->getLocationsFacadeSomehow();

$locations = Helpers::expandTreeValues($facade, $locations);
$where = Helpers::prepareWhereClauseForChildren($facade, $locations);

Helpers::updateWithTreeEntity($qb, $locations, $where->where, $where->parameters);

return $qb;
}

关于php - 在 MySQL 树中搜索具有多对多关联的项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22695918/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com