1

私は、多(証明書)対1(ポリシー)の関係にある2つの(この質問に関連する)エンティティを持っています:

  • 証明書
  • ポリシー

...基本的には次のようになります。

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;
}

removeTemplate()(もちろん、対応する getter と setter は doctrine によって自動生成されます) このアプローチの問題は、それ自体が-function を呼び出すコントローラーを呼び出すとAllowed memory size of 134217728 bytes exhausted (tried to allocate [...] bytes) in [...]、問題は、証明書オブジェクトを取得してそのプロパティをテストする foreach-loop だと思いますisTemplate。証明書オブジェクトは非常に大きいため、約 80 個以上の証明書がある場合、メモリ使用量が高くなりすぎます (エラー メッセージが表示されます)。

どうすればこの問題を解決できるのだろうか。私には 2 つのアイデア / アプローチがありましたが、期待どおりに機能しませんでした。

最初のものは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 エンティティのオブジェクトです)。

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

(このStackOverflow-answer$pol->getId()のため、 Policy-objectの代わりに を使用しました)

このアプローチの問題は、常にエラーが発生し、そのUnrecognized field: policies理由がわからないことです。

誰かがこれらのアプローチの1つを機能させるのを手伝ってくれることを願っています(コントローラーで何も変更する必要がないので、最初のアプローチを好むでしょう)。

前もってありがとう、katze_sonne

4

1 に答える 1

1

2 つのソリューション:

  • 結果をページ付けすることができます
  • 結果を配列に水和できます

あなたはこのようなことをすることができます

$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 に答える