使用自定义方法扩展实体以过滤Symfony2中的关系

时间:2014-08-08 10:31:17

标签: php symfony doctrine-orm

我正在寻找一种方法来扩展我的Symfony2(我目前使用2.3)Entity类,并使用一种方法来有效地按需过滤其关系。所以,成像我有两个OneToMany关系的类:

/**
 * ME\MyBundle\Entity\Kindergarten
 */
class Kindergarten
{
    /**
     * @var integer $id
     */
    private $id;

    /**
     * @var ME\MyBundle\Entity\Kinder
     */
    private $kinders;

    public function __construct()
    {
         $this->kinders = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get kinders
     *
     * @return Doctrine\Common\Collections\Collection
     */
    public function getKinders()
    {
        return $this->kinders;
    }
}

/**
 * ME\MyBundle\Entity\Kinder
 */
class Kinder
{
    /**
     * @var integer $id
     */
    private $id;

    /**
     * @var string $name
     */
    private $name;

    /**
     * @var integer $age
     */
    private $age;
}

我的目标是在Kindergarten课程上设置一个方法,以便按需提供所有年龄较大的方法,例如10到12之间:

   $myKindergarten->getKindersByAgeInInterval(10,12);

当然,我可以这样做:

class Kindergarten
{
   ...

   public function getKindersByAgeInInterval($start, $end)
   {
        return $this->getKinders()->filter(
            function($kinder) use ($start, $end)
            {
                $kinderAge = $kinder->getAge();
                if($kinderAge < $start || $kinderAge > $end)
                {
                    return false;
                }
                return true;
            }
        );
   }

   ...
}

上面的解决方案可行,但效率非常低,因为我需要迭代所有kinder,这可能是一个非常大的列表,无法缓存这些过滤器。我在考虑使用Criteria类或一些代理模式,但不确定在Symfony2中做得好的方法,特别是因为它们可能需要访问EntityManager

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我建议将此责任提取到EntityRepository

<?php
class KinderRepository extends \Doctrine\ORM\EntityRepository
{

    public function findByKindergartenAndAge(Kindergarten $entity, $minAge = 10, $maxAge = 20)
    {
        return $this->createQueryBuilder()
                    ->... // your query logic here
    }

}

所有查找都应该在您有权访问实体管理器的类中进行。

这实际上是Doctrine架构所建议的方式。您永远无法访问您实体的任何服务,如果您认为自己需要它,那么您的架构就会出现问题。

当然,如果您以后决定添加更多标准(想象您将按照幼儿园,年龄,体重和身高进行搜索),您可能会觉得存储库方法可能会变得非常难看,请参阅{{3 }})。然后你应该考虑实现更多的逻辑,但同样,这不应该是必要的。