我正在寻找一种方法来扩展我的Symfony2
(我目前使用2.3)Entity
类的方法,以有效地过滤其按需关系。所以,成像我有这样两个类与OneToMany
的关系:
/**
* MEMyBundleEntityKindergarten
*/
class Kindergarten
{
/**
* @var integer $id
*/
private $id;
/**
* @var MEMyBundleEntityKinder
*/
private $kinders;
public function __construct()
{
$this->kinders = new DoctrineCommonCollectionsArrayCollection();
}
/**
* Get kinders
*
* @return DoctrineCommonCollectionsCollection
*/
public function getKinders()
{
return $this->kinders;
}
}
/**
* MEMyBundleEntityKinder
*/
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 DoctrineORMEntityRepository
{
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),那么您可能会想到存储库方法可能会变得非常难看。然后,您应该考虑实现更多的逻辑,但同样,这应该不是那么必要。