我将 Doctrine 和 ResultSetMappingBuilder 与addMetaResult()
一起使用。 我在我的存储库中获得了本机查询,并映射到实体,它运行良好,代码结构如下所示:
$rsm = new ResultSetMappingBuilder($entityManager);
$rsm->addRootEntityFromClassMetadata('AppBundleEntityExample', 'e');
$rsm->addFieldResult('e', 'id', 'id');
$rsm->addMetaResult('e', 'value', 'value');
$sql = "SELECT id, 5 as value FROM table";
$query = $entityManager->createNativeQuery($sql, $rsm)
$result = $query->getResult();
我的实体.yml看起来像这样:
AppBundleEntityExample:
...
fields:
id:
type: smallint
nullable: false
options:
unsigned: true
id: true
generator:
strategy: IDENTITY
value:
type: integer
但是当我在其他地方使用该实体时,请使用如下所示的标准实体管理器方法:
$this->exampleRepo->find(5);
然后我得到错误:
找不到列:1054 "字段列表"中的未知列"t0.value">
这是因为我的表中没有真正的列"值",它是元列。是否有任何配置可以跳过该列(如果它不在本机查询中(,或者如果它不存在,或者我必须覆盖存储库中的方法find()
并在其中添加映射?
看看这个问题,这个答案和这个问题的这个答案,了解更多背景。
简短的回答是,您遇到了 Doctrine 的限制,因为您不能拥有看似数据库列但实际上不是的虚拟属性。 因此,当您将其添加到您的entity.yml 时:
value:
type: integer
您告诉 Doctrine 的是,您的示例实体上有一个值列。 因此,您尝试运行的任何Doctrine 查询都会中断。 原始查询不这样做的原因是,您正在运行本机查询并自己显式执行映射。
所以你可能觉得你找到了一种方法来解决教义的局限性,但你没有。
最简单的解决方案是在示例实体中维护一个非映射值字段,然后当您需要查询该字段时,只需将其添加到 Doctrine 查询中,然后手动设置所需的内容。 像这样:
$entityResults = [];
/**
* return array of arrays like: [
* ['example' => Example entity, 'value' => int value],
* ['example' => Example entity, 'value' => int value],
* ]
*/
$results = $em
->createQuery('SELECT e AS example, 5 AS value FROM AppBundle:Example')
->getResult();
foreach ($results as $result) {
$result['example']->setValue($result['value]);
$entityResults[] = $result['example'];
}
return $entityResults;
如果你想要一些更全球化的东西,你可以考虑添加一个定制的水合器。