【发布时间】:2017-10-03 14:05:31
【问题描述】:
链接存储库方法以重用查询构建逻辑的最佳实践是什么?
这是我的做法,但我怀疑这是否正确:
use Doctrine\ORM\Mapping;
use Doctrine\ORM\EntityManager;
class OrderRepository extends \Doctrine\ORM\EntityRepository
{
private $q;
public function __construct(EntityManager $em, Mapping\ClassMetadata $class)
{
parent::__construct($em, $class);
$this->q = $this->createQueryBuilder('o');
}
public function getOneResult()
{
return $this->q->getQuery()->getOneOrNullResult();
}
public function getResult()
{
return $this->q->getQuery()->getResult();
}
public function filterByStatus($status)
{
$this->q->andWhere('o.status = :status')->setParameter('status', $status);
return $this;
}
public function findNextForPackaging()
{
$this->q->leftjoin('o.orderProducts', 'p')
->orderBy('o.deliveryDate', 'ASC')
->andHaving('SUM(p.qtePacked) < SUM(p.qte)')
->groupBy('o.id')
->setMaxResults(1);
return $this;
}
}
这允许我像这样链接方法:
$order = $em->getRepository('AppBundle:Order')->filterByStatus(10)->findNextForPackaging()->getOneResult();
这当然只是一个例子。实际上还有更多的方法可以链接。
其中一个大问题是我需要为某些“过滤器”加入连接,因此我必须在添加之前检查连接是否已由某些方法/过滤器设置。 (示例中我没有放,但想通了,但不是很漂亮)
另一个问题是我在使用存储库时必须小心,因为查询可能已经设置了一些东西,所以每次使用前我都需要重置查询。
我也知道我可以使用带有标准的学说“匹配”方法,但据我了解,这相当昂贵,而且我不知道如何用这种方法解决“加入”问题.
有什么想法吗?
【问题讨论】:
-
你绝对不想要你自己的构造函数。如果您不使用 EntityManager::getRepository 工厂方法,那么您将遇到许多有趣的工作单元问题。
-
我发现您让一些查找方法返回存储库的方法以及“隐藏”查询构建器的概念有点令人困惑,并且可能难以维护。只要确保你真的有足够的过滤器让它值得。
-
你完全正确!这就是为什么我正在寻找更好的解决方案...
-
我考虑过使用 SQLFilters,但这似乎有点过头了
-
通过扩展
Doctrine\ORM\QueryBuilder创建一个新的 QueryBuilder,添加您自己的方法并在您的存储库中覆盖createQueryBuilder以返回您自己的构建器类,而不是默认的。
标签: php symfony doctrine-orm repository