【问题标题】:Symfony Doctrine Hydrator - With custom hydrator I lose my ManyToOne relationSymfony Doctrine Hydrator - 使用自定义 hydrator 我失去了 ManyToOne 关系
【发布时间】:2017-09-12 01:28:01
【问题描述】:

我想扩展 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.yml

doctrine:
    orm:
        hydrators:
            project_assignment_statisticsdata_hydrator: Doctrine\ORM\Internal\Hydration\ObjectHydrator

我尝试了各种获取关系但没有成功:

@ORM\ManyToOne(... , fetch="EAGER")
@ORM\ManyToOne(... , fetch="LAZY")
...

也许我必须在我的实体上使用代理,我真的不知道:(

感谢您的帮助!

【问题讨论】:

    标签: symfony doctrine-orm doctrine many-to-one hydration


    【解决方案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');
    }
    

    奖励,这是我的 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 的 ObjectHydrator 的精确副本,但由于某种原因,代理类没有加载。必须有更好的方法来解决这个问题。
    【解决方案2】:

    问题是Doctrine SqlWalker 不会加载包含子类和关联的元列,如果查询 Hydration Mode 不是 HYDRATE_OBJECT 或查询提示 HINT_INCLUDE_META_COLUMNS 未设置为 true:

    $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);
    

    该问题已在this issue 中报告。

    正如问题作者所说,您可以实施建议的修复,或将查询提示 HINT_INCLUDE_META_COLUMNS 设置为 true:

    $query = $queryBuilder->getQuery();
    $query->setHint(Query::HINT_INCLUDE_META_COLUMNS, true);
    $result = $query->getResult('CustomHydrator');
    

    【讨论】:

      猜你喜欢
      • 2014-08-11
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多