1

我有两个(对于这个问题相关的)实体,它们处于多(证书)对一个(策略)关系中:

  • 证书
  • 政策

...基本上看起来像这样:

class Policy {
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="Akm\CertificateBundle\Entity\Certificate", mappedBy="policies")
     */
    private $certificates;

    /**
     * Get template (assuming there is only one
     * per policy (which should be the case) and return the Certificate
     * object. If (for some reason) there is more than only one template,
     * then only the first one will be returned.
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getTemplate() {
        $certificates = $this->getCertificates();
        foreach($certificates as $cert) {
           if ($cert->getIsTemplate()) {
              return $cert;
           }
        }
        return false;
    }
}

和:

class Certificate {
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="boolean", nullable=false)
     */
    private $isTemplate;

    /**
     * @ORM\ManyToOne(targetEntity="Akm\CertificateBundle\Entity\Policy", inversedBy="certificates")
     * @ORM\JoinColumn(name="policy_id", referencedColumnName="id", nullable=true)
     */
    private $policies;
}

(当然还有相应的 getter 和 setter,由学说自动生成)这种方法的问题是,如果我调用一个控制器,它本身调用removeTemplate()-function,我得到一个Allowed memory size of 134217728 bytes exhausted (tried to allocate [...] bytes) in [...]; 我认为,问题在于 foreach 循环,它获取证书对象并测试其属性isTemplate。因为证书对象非常大,如果大约有 80 个或更多证书,这会导致内存使用率过高(导致错误消息)。

现在我想知道,我该如何解决这个问题。我有两个想法/方法,但没有按预期工作。

第一个是我知道unset()$cert- 变量,我不再需要它了:

public function getTemplate() {
    $certificates = $this->getCertificates();
    foreach($certificates as $cert) {
       if ($cert->getIsTemplate()) {
          return $cert;
       } else {
          unset($cert);
       }
    }
    return false;
}

然而,这并没有改变任何东西,控制器仍然使用相同数量的内存。

所以我考虑用getTemplate()以下内容替换控制器内的所有 -function 调用(其中$pol-variable 是 Policy-entity 的对象):

$template = $cert_repository->findBy(
                    array('isTemplate' => true),
                    array('policies' => $pol->getId());

$pol->getId()(由于这个StackOverflow-answer ,我使用了Policy-object 而不是仅使用了 Policy-object )

这种方法的问题是,我总是得到一个Unrecognized field: policies-error,我不知道为什么。

我希望有人可以帮助我使其中一种方法起作用(我更喜欢第一种,因为那时我不必更改控制器中的任何东西)。

在此先感谢, katze_sonne

4

1 回答 1

1

两种解决方案:

  • 您可以对结果进行分页
  • 您可以将结果水合到数组中

你可以做这样的事情

$query = $this->cert_repository
              ->createQueryBuilder('p')
              ->select(array('p'))
              ->where('p.isTemplate = :isTemplate')->setParameter('isTemplate', true)
              ->andWhere('p.policies = :policies')->setParameter('policies', $pol->getId())
              ->getQuery()
              ->setFirstResult($offset)
              ->setMaxResults($limit);
return $query->getArrayResult();

基本上,当 Doctrine 对对象进行水合时,它会将对象数据的引用保存到内存中,并且使用该函数unset不会释放内存,但是将对象水合为数组可以让您使用该函数unset

于 2013-10-21T17:33:43.407 回答