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


Extend Entity with custom method to filter relations in Symfony2

我正在寻找一种方法来扩展我的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;
            }
        );
   }
   ...
}

上面的解决方案可以工作,但它非常低效,因为我需要遍历所有类型,这可能是一个非常大的列表,并且没有办法缓存这样的过滤器。我想使用Criteria类或一些代理模式,但不确定如何在Symfony2中做到这一点,特别是因为他们可能需要访问EntityManager

任何想法?

我建议将此职责提取到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架构所建议的方式。你永远不能从你的实体访问任何服务,如果你曾经认为你需要它,那么,你的体系结构出了问题。

当然,如果您以后决定添加更多的条件(假设您还将按幼儿园、年龄、体重和身高进行搜索,请参阅http://www.whitewashing.de/2013/03/04/doctrine_repositories.html),那么您可能会想到存储库方法可能会变得非常难看。然后,您应该考虑实现更多的逻辑,但同样,这应该不是那么必要。