Doctrine2 查询生成器 - 关联数据未正确补水
Doctrine2 Query Builder - Associative Data not hydrating correctly
我在 X-Cart 项目上写了一个有点复杂的查询(使用 doctrine 作为 ORM)。我必须 query/pull 来自多个表的记录,并确保我不会在相关数据中返回 irrelevant/empty 结果。以下是我 运行 感兴趣的内容:
我有几个内部联接,它们应该只提取具有关联数据的记录。我已经让查询吐出它生成的原始 SQL,并且当 运行 直接针对 MySQL 数据库时它可以 100% 工作。
我认为问题是在混合基础模型的关联数据时出现的。
public function getAlbums() {
// Query Parameters
$params = $this->params;
// Base Query
// TO DO: Associated data is not being hydrated properly by the joins,
$query = \XLite\Core\Database::getRepo('\XLite\Module\CodeSmith\Albums\Model\Album')
->createQueryBuilder('album')
->linkInner('album.songs', 'song')
->linkInner('song.song_tracks', 'song_track')
->linkInner('song_track.album_track', 'track');
// Init conditions array
$conditions = [];
// If school_type is present, check against song's school type
if(isset($params['school_type'])){
$conditions[] = $query->expr()->eq('song.school_type', $params['school_type']);
}
// If track type is present, check against album_track's track type
if(isset($params['track_type'])){
$conditions[] = $query->expr()->eq('track.track_type', "'{$params['track_type']}'");
}
// If album name is present, generate OR expression to check against first letter of album name
// i.e. (first_letter = A OR first_letter = B OR first_letter = C)
if(isset($params['album_name'])){
$orX = $query->expr()->orX();
$name_conditions = array_map(function($letter) use ($query){
return $query->expr()->eq($query->expr()->substring('album.name', 1, 1), "'$letter'");
}, explode(',', $params['album_name']));
$orX->addMultiple($name_conditions);
$conditions[] = $orX;
}
if(isset($params['category'])){
// TO DO
}
if(isset($params['text'])){
// TO DO
}
// Aggregate conditions array with AND
if(count($conditions)){
$conditions = call_user_func_array(array($query->expr(), 'andx'), $conditions);
$query->where($conditions);
}
// Fetch Results
$albums = $query->getQuery()->getResult();
return $albums;
}
相关数据只是与所有相关数据一起返回。我不想要所有相关条目,只想要符合搜索条件的条目。这是 Doctrine 的问题还是我做的不对?
终于搞清楚了。我需要利用 "fetch" 连接来确保相关数据正确混合。 Doctrine 的文档仅通过 createQuery
而不是通过查询构建器显示它的示例。
这是我的旧代码:
$query = \XLite\Core\Database::getRepo('\XLite\Module\CodeSmith\Albums\Model\Album')
->createQueryBuilder('album')
->linkInner('album.songs', 'song')
->linkInner('song.song_tracks', 'song_track')
->linkInner('song_track.album_track', 'track');
这是通过 createQueryBuilder
完成的方法:
$query = \XLite\Core\Database::getEM()->createQueryBuilder()
->select('album, song, song_track, track')
->from('\XLite\Module\CodeSmith\Albums\Model\Album', 'album')
->innerJoin('album.songs', 'song')
->innerJoin('song.song_tracks', 'song_track')
->innerJoin('song_track.album_track', 'track');
select 语句是确保获取的内容。
我在 X-Cart 项目上写了一个有点复杂的查询(使用 doctrine 作为 ORM)。我必须 query/pull 来自多个表的记录,并确保我不会在相关数据中返回 irrelevant/empty 结果。以下是我 运行 感兴趣的内容:
我有几个内部联接,它们应该只提取具有关联数据的记录。我已经让查询吐出它生成的原始 SQL,并且当 运行 直接针对 MySQL 数据库时它可以 100% 工作。
我认为问题是在混合基础模型的关联数据时出现的。
public function getAlbums() {
// Query Parameters
$params = $this->params;
// Base Query
// TO DO: Associated data is not being hydrated properly by the joins,
$query = \XLite\Core\Database::getRepo('\XLite\Module\CodeSmith\Albums\Model\Album')
->createQueryBuilder('album')
->linkInner('album.songs', 'song')
->linkInner('song.song_tracks', 'song_track')
->linkInner('song_track.album_track', 'track');
// Init conditions array
$conditions = [];
// If school_type is present, check against song's school type
if(isset($params['school_type'])){
$conditions[] = $query->expr()->eq('song.school_type', $params['school_type']);
}
// If track type is present, check against album_track's track type
if(isset($params['track_type'])){
$conditions[] = $query->expr()->eq('track.track_type', "'{$params['track_type']}'");
}
// If album name is present, generate OR expression to check against first letter of album name
// i.e. (first_letter = A OR first_letter = B OR first_letter = C)
if(isset($params['album_name'])){
$orX = $query->expr()->orX();
$name_conditions = array_map(function($letter) use ($query){
return $query->expr()->eq($query->expr()->substring('album.name', 1, 1), "'$letter'");
}, explode(',', $params['album_name']));
$orX->addMultiple($name_conditions);
$conditions[] = $orX;
}
if(isset($params['category'])){
// TO DO
}
if(isset($params['text'])){
// TO DO
}
// Aggregate conditions array with AND
if(count($conditions)){
$conditions = call_user_func_array(array($query->expr(), 'andx'), $conditions);
$query->where($conditions);
}
// Fetch Results
$albums = $query->getQuery()->getResult();
return $albums;
}
相关数据只是与所有相关数据一起返回。我不想要所有相关条目,只想要符合搜索条件的条目。这是 Doctrine 的问题还是我做的不对?
终于搞清楚了。我需要利用 "fetch" 连接来确保相关数据正确混合。 Doctrine 的文档仅通过 createQuery
而不是通过查询构建器显示它的示例。
这是我的旧代码:
$query = \XLite\Core\Database::getRepo('\XLite\Module\CodeSmith\Albums\Model\Album')
->createQueryBuilder('album')
->linkInner('album.songs', 'song')
->linkInner('song.song_tracks', 'song_track')
->linkInner('song_track.album_track', 'track');
这是通过 createQueryBuilder
完成的方法:
$query = \XLite\Core\Database::getEM()->createQueryBuilder()
->select('album, song, song_track, track')
->from('\XLite\Module\CodeSmith\Albums\Model\Album', 'album')
->innerJoin('album.songs', 'song')
->innerJoin('song.song_tracks', 'song_track')
->innerJoin('song_track.album_track', 'track');
select 语句是确保获取的内容。