詳細な調査の後、他の回答に記載されているものに近いものをいくつか見つけましたが、それらのすべてにはいくつかの欠点があります。最後にCustomHydratorsを使用することに決めました。 ORMで管理されていないプロパティは、フィールドとしてResultSetMappingでマッピングすることはできませんが、スカラーとして取得してエンティティに手動で追加することができます。しかし、あなたが教義から得た結果はキャッシュに残っています。つまり、これらのエンティティも含む他のクエリを作成すると、そのように設定されたプロパティがリセットされる可能性があります。
これを行う別の方法は、これらのフィールドをdoctrineのメタデータキャッシュに直接追加することでした。私はCustomHydratorでこれをやってみました:しかし、その方法はエンティティのプロパティのリセットにも問題がありました。だから、私の最終的な解決策は、同じ構造を得るためにはstdClassを使用するだけだったが、教義によって管理されていない:あなたはどのような構造を取得し、あなたが好きしかし、任意のエンティティを添付することができ、そのクラスで
namespace SomeBundle;
use PDO;
use Doctrine\ORM\Query\ResultSetMapping;
class CustomHydrator extends \Doctrine\ORM\Internal\Hydration\ObjectHydrator {
public function hydrateAll($stmt, $resultSetMapping, array $hints = array()) {
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
$result = [];
foreach($resultSetMapping->entityMappings as $root => $something) {
$rootIDField = $this->getIDFieldName($root, $resultSetMapping);
foreach($data as $row) {
$key = $this->findEntityByID($result, $row[$rootIDField]);
if ($key === null) {
$result[] = new \stdClass();
end($result);
$key = key($result);
}
foreach ($row as $column => $field)
if (isset($resultSetMapping->columnOwnerMap[$column]))
$this->attach($result[$key], $field, $this->getPath($root, $resultSetMapping, $column));
}
}
return $result;
}
private function getIDFieldName($entityAlias, ResultSetMapping $rsm) {
foreach ($rsm->fieldMappings as $key => $field)
if ($field === 'ID' && $rsm->columnOwnerMap[$key] === $entityAlias) return $key;
return null;
}
private function findEntityByID($array, $ID) {
foreach($array as $index => $entity)
if (isset($entity->ID) && $entity->ID === $ID) return $index;
return null;
}
private function getPath($root, ResultSetMapping $rsm, $column) {
$path = [$rsm->fieldMappings[$column]];
if ($rsm->columnOwnerMap[$column] !== $root)
array_splice($path, 0, 0, $this->getParent($root, $rsm, $rsm->columnOwnerMap[$column]));
return $path;
}
private function getParent($root, ResultSetMapping $rsm, $entityAlias) {
$path = [];
if (isset($rsm->parentAliasMap[$entityAlias])) {
$path[] = $rsm->relationMap[$entityAlias];
array_splice($path, 0, 0, $this->getParent($root, $rsm, array_search($rsm->parentAliasMap[$entityAlias], $rsm->relationMap)));
}
return $path;
}
private function attach($object, $field, $place) {
if (count($place) > 1) {
$prop = $place[0];
array_splice($place, 0, 1);
if (!isset($object->{$prop})) $object->{$prop} = new \stdClass();
$this->attach($object->{$prop}, $field, $place);
} else {
$prop = $place[0];
$object->{$prop} = $field;
}
}
}
:
$sql = '
SELECT p.*, COUNT(r.id)
FROM products p
LEFT JOIN reviews r ON p.id = r.product_id
';
$em = $this->getDoctrine()->getManager();
$rsm = new ResultSetMapping();
$rsm->addEntityResult('SomeBundle\Entity\Product', 'p');
$rsm->addFieldResult('p', 'COUNT(id)', 'reviewsCount');
$query = $em->createNativeQuery($sql, $rsm);
$em->getConfiguration()->addCustomHydrationMode('CustomHydrator', 'SomeBundle\CustomHydrator');
$results = $query->getResult('CustomHydrator');
誰かを助けることができる希望:
私はそうは思わない。名前付きクエリの使用を検討しましたか?[example](http://stackoverflow.com/questions/12016378/doctrine2-named-queries)? –
はい。私はTomasz Madeyskiの答えに対する私のコメントでネイティブクエリーの問題に気づいた。問題は、スカラーをエンティティと一緒に返すことですが、私はそれらをエンティティのフィールドにして混乱を避けたいと考えています。 – Multis