Doctrine 在部分查询后获得完整的实体

Doctrine get full entity after a partial query

我正在开发一个使用 Zend Framework 2 和 Doctrine 2 构建的系统。

在这个系统中,我正在处理合同部分,我想要一个包含来自所有合同的一些数据(部分查询)的列表,我需要填写一个包含来自特定合同的所有数据(实体查找)的表格.

但是由于表单中要填写的合同也是partial查询的结果,所以PARTIAL查询中没有加载的属性也不会被查询实体加载。

我简化了数据以仅显示当前问题,真实实体有更多字段:

实体:

use Doctrine\ORM\Mapping as ORM;

/**
 * ContractSub
 *
 * @ORM\Table(name="contract_sub", indexes={@ORM\Index(name="contract_id", columns={"contract_id"}), @ORM\Index(name="list_pension_start", columns={"list_pension_start_id"}), @ORM\Index(name="list_lease_car_category", columns={"list_lease_car_category_id"}), @ORM\Index(name="created_by_id", columns={"created_by_id"})})
 * @ORM\Entity(repositoryClass="Application\Repository\ContractSubRepository")
 * @ORM\HasLifecycleCallbacks
 */
class ContractSub
{

    /**
     *
     * @var integer @ORM\Column(name="id", type="integer", nullable=false)
     *      @ORM\Id
     *      @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     *
     * @var \DateTime @ORM\Column(name="start_date", type="date", nullable=false)
     */
    private $startDate;

    /**
     *
     * @var \DateTime @ORM\Column(name="end_date", type="date", nullable=true)
     */
    private $endDate;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set startDate
     *
     * @param \DateTime $startDate            
     *
     * @return ContractSub
     */
    public function setStartDate($startDate)
    {
        $this->startDate = $startDate;

        return $this;
    }

    /**
     * Get startDate
     *
     * @return \DateTime
     */
    public function getStartDate()
    {
        return $this->startDate;
    }

    /**
     * Set endDate
     *
     * @param \DateTime $endDate            
     *
     * @return ContractSub
     */
    public function setEndDate($endDate)
    {
        $this->endDate = $endDate;

        return $this;
    }

    /**
     * Get endDate
     *
     * @return \DateTime
     */
    public function getEndDate()
    {
        return $this->endDate;
    }
}

存储库:

use Doctrine\ORM\EntityRepository;

class ContractSubRepository extends EntityRepository
{

    public function getPartialStuffForTest()
    {
        $oQuery = $this->_em->createQuery('SELECT PARTIAL ContractSub.{id, startDate} 
                                           FROM Application\Entity\ContractSub ContractSub');
        return $oQuery->getResult();
    }
}

控制器:

use Zend\Mvc\Controller\AbstractActionController;

class ContractController extends AbstractActionController
{
    public function testAction()
    {
        $oEntityManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
        $aContracts = $oEntityManager->getRepository('Application\Entity\ContractSub')->getPartialStuffForTest();
        $oContractSub = $oEntityManager->getRepository('Application\Entity\ContractSub')->find(38);
        var_dump($oContractSub->getStartDate());
        var_dump($oContractSub->getEndDate());
        die();
    }
}

这输出:

object(DateTime)[479]
  public 'date' => string '2015-06-01 00:00:00.000000' (length=26)
  public 'timezone_type' => int 3
  public 'timezone' => string 'Europe/Amsterdam' (length=16)

null

表示 endDate 未加载,即使我执行了 find 以检索完整的实体。 当我评论执行 getPartialStuffForTest() 的行时,我也得到了 endDate

所以我想知道是否有任何方法可以强制 Doctrine 在已经具有部分实体的缓存版本后检索完整实体?

要完全加载部分内容,您必须使用 $entityManager->refresh($object)

您的答案在the first paragraph in the Doctrine2 documentation chapter 18. Partial objects

Use of partial objects is tricky. Fields that are not retrieved from the database will not be updated by the UnitOfWork even if they get changed in your objects. You can only promote a partial object to a fully-loaded object by calling EntityManager#refresh() or a DQL query with the refresh flag.