Symfony Doctrine Hydrator - с пользовательским гидратором я теряю отношения ManyToOne
Я хотел бы расширить ObjectHydrator, чтобы улучшить гидратацию моего отношения ManyToOne и добавить дополнительное поле к сущности.
Вот мой гидратор: StatisticsDataHydrator.php
namespace AppBundle\Hydrator\ProjectAssignment;
use AppBundle\Entity\ProjectAssignment;
use Doctrine\ORM\Internal\Hydration\ObjectHydrator;
class StatisticsDataHydrator extends ObjectHydrator
{
/**
* {@inheritdoc}
*/
protected function hydrateRowData(array $data, array &$result)
{
$hydrated_result = array();
parent::hydrateRowData($data, $hydrated_result);
/** @var ProjectAssignment $project_assignment */
$project_assignment = $hydrated_result[0][0];
$result[] = $project_assignment;
}
}
Вот мой конфиг: config.yml
doctrine:
orm:
hydrators:
project_assignment_statisticsdata_hydrator: AppBundle\Hydrator\ProjectAssignment\StatisticsDataHydrator
Где я не использую гидратор, у меня нет проблем:
/**
* @param ProjectStage $stage
* @return array
*/
public function findByStageWithStatisticsData(ProjectStage $stage){
$qb = $this->createQueryBuilder('pa');
$qb
//->addSelect('44')
->where($qb->expr()->eq('pa.project_stage', ':stage'))
->setParameter('stage', $stage);
return $qb->getQuery()->getResult();
}
Но когда я использую мой гидратор:
/**
* @param ProjectStage $stage
* @return array
*/
public function findByStageWithStatisticsData(ProjectStage $stage){
$qb = $this->createQueryBuilder('pa');
$qb
->addSelect('1234') // referencial value
->where($qb->expr()->eq('pa.project_stage', ':stage'))
->setParameter('stage', $stage);
return $qb->getQuery()->getResult('project_assignment_statisticsdata_hydrator');
}
Самое странное поведение - то же самое происходит с этим config: config.yml
doctrine:
orm:
hydrators:
project_assignment_statisticsdata_hydrator: Doctrine\ORM\Internal\Hydration\ObjectHydrator
Я перепробовал все виды отношений без успеха:
@ORM\ManyToOne(... , fetch="EAGER")
@ORM\ManyToOne(... , fetch="LAZY")
...
Может быть, я должен использовать прокси на моей сущности, я действительно не знаю:(
Спасибо за любую помощь!
1 ответ
Большой! Я нашел проблему, это было с моим конструктором запросов. Мне пришлось вручную добавлять объединения и выбирать связанные объекты.
/**
* @param ProjectStage $stage
* @return array
*/
public function findByStageWithStatisticsData(ProjectStage $stage){
$qb = $this->createQueryBuilder('pa');
$qb
->addSelect('e') // added
->addSelect('r') // added
->addSelect('1234')
->leftJoin('pa.employee', 'e') // added
->leftJoin('pa.role', 'r') // added
->where($qb->expr()->eq('pa.project_stage', ':stage'))
->setParameter('stage', $stage);
return $qb->getQuery()->getResult('project_assignment_statisticsdata_hydrator');
}
Бонус, вот мой Гидратор (он может кому-то помочь):
namespace AppBundle\Hydrator\ProjectAssignment;
use AppBundle\Entity\Hydrator\ProjectAssignment\StatisticsData;
use AppBundle\Entity\ProjectAssignment;
use Doctrine\ORM\Internal\Hydration\ObjectHydrator;
class StatisticsDataHydrator extends ObjectHydrator
{
/**
* {@inheritdoc}
*/
protected function hydrateRowData(array $data, array &$result)
{
$hydrated_result = array();
parent::hydrateRowData($data, $hydrated_result);
/** @var ProjectAssignment $project_assignment */
$project_assignment = $hydrated_result[0][0];
$keys = array_keys($hydrated_result); $key = end($keys);
$statistics_data = new StatisticsData($project_assignment);
$statistics_data->setTotalWorkedTime((int)$hydrated_result[$key][1]);
$project_assignment->setStatisticsData($statistics_data);
$result[] = $project_assignment;
}
}
В моей сущности у меня есть следующий атрибут /getter/setter
/********** NON SYNCED FIELDS **********/
/** @var StatisticsData $statistics_data */
private $statistics_data;
/**
* @return StatisticsData
*/
public function getStatisticsData()
{
return $this->statistics_data;
}
/**
* @param StatisticsData $statistics_data
*/
public function setStatisticsData($statistics_data)
{
$this->statistics_data = $statistics_data;
}
/***************************************/
Проблема в том, что Doctrine SqlWalker не будет загружать мета-столбцы, которые включают подклассы и ассоциации, если запрос Hydration Mode не HYDRATE_OBJECT
или если запрос подсказка HINT_INCLUDE_META_COLUMNS
к истине:
$addMetaColumns = ! $this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD) &&
$this->query->getHydrationMode() == Query::HYDRATE_OBJECT
||
$this->query->getHydrationMode() != Query::HYDRATE_OBJECT &&
$this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS);
О проблеме уже сообщалось в этом выпуске.
Как уже упоминалось автором проблемы, вы можете либо внедрить предложенное исправление, либо установить подсказку к запросу. HINT_INCLUDE_META_COLUMNS
к истине:
$query = $queryBuilder->getQuery();
$query->setHint(Query::HINT_INCLUDE_META_COLUMNS, true);
$result = $query->getResult('CustomHydrator');