如何有效地加载 ArrayCollection 中的最后一项?

How to efficiently load last item in ArrayCollection?

我有以下 2 个实体:

public class Domain {
    ...
    /**
    * @ORM\OneToMany(targetEntity="Application\Entity\Ping", mappedBy="domain", cascade={"persist", "remove"}, fetch="EXTRA_LAZY")
    * @ORM\OrderBy({"time" = "ASC"})
    */
    private $pings;
    ...
}

和:

class Ping{
    ...
    /**
     * @ORM\ManyToOne(targetEntity="Application\Entity\Domain", inversedBy="pings")
     * @ORM\JoinColumn(name="proj_id", referencedColumnName="proj_id")
    */
    private $domain;
    ...
 }

我目前有几百个域,每个域的 Ping 值在我的表中。

在域概览中 - 每页限制为 50 个域 - 我想显示所有 ping 的计数和最后一个 ping 的结果。虽然显示集合的计数没有任何问题,但我无法有效地获取集合的最后一个元素。

我试图通过

获取元素
$domain->getPings()->last();

$domain->getPings()->get( $key );

两种情况下的结果是一样的:

Allowed memory size of 134217728 bytes exhausted ...

我怎样才能有效地获得最后的 ping?

要在不需要存储库的情况下在实体中有效地过滤您的集合,您可以使用 Criteria。它将允许过滤已经加载到内存中的集合,或者如果没有则直接在 sql 中执行。引用文档:

If the collection has not been loaded from the database yet, the filtering API can work on the SQL level to make optimized access to large collections

只需将以下方法添加到您的 Domain 实体。

use Doctrine\Common\Collections\Criteria;

// ...

/**
 * Get last ping for the domain.
 * @returns Ping
 */
public function getLastPing()
{
    $c = Criteria::create();
    $c->setMaxResults(1);
    $c->orderBy(['time' => Criteria::DESC]);
    $this->pings->matching($c)->first();
}