实体和存储库中的 Doctrine 可重用条件与连接
Doctrine reusable Criteria in Entity and Repository with joins
我已经搜索这个特定问题很长时间了,不确定我是否对在查询中使用 Criteria 有误解,或者它是否不可能(现在?)
这是一个只有最少字段和条件的示例。
我有两个实体:
- 产品
- 字段:可见
- 品牌
- 字段:活动
在品牌实体中,我有一个方法
"getVisibleProducts()"
我想在其中获取所有产品
product.visible = 1
在我的 ProductRepository 中,我有一个方法 findAllVisibleForBrand(Brand $brand)
,我想在其中获取具有 product.visible = 1
和 brand.active = 1
的所有产品
所以我的最佳可重用性想法是为我的 ProductRepository 中的 product.visible
值制定一个标准,并将其用于存储库中的查询
/**
* @param Brand $brand
*
* @return Product[]
*/
public function findAllVisibleForBrand(Brand $brand)
{
return $this->createQueryBuilder('product')
->leftJoin('product.brand', 'brand')
->addCriteria(ProductRepository::createVisibleCriteria())
->andWhere('product.brand = :brand')
->setParameter('brand', $brand)
->getQuery()
->execute();
;
}
/**
* @return Criteria
*/
public static function createVisibleCriteria()
{
return Criteria::create()
->andWhere(Criteria::expr()->eq('visible', '1'))
;
}
在我的品牌实体中:
/**
* @return Product[]|ArrayCollection
*/
public function getVisibleProducts()
{
return $this->getProducts()->matching(ProductRepository::createVisibleCriteria());
}
这工作正常,没有问题。
BrandRepository 的想法相同
/**
* @return Brand[]
*/
public function findAllActiveBrands()
{
return $this->createQueryBuilder('brand')
->addCriteria(BrandRepository::createActiveCriteria())
->getQuery()
->execute()
;
}
/**
* @return Criteria
*/
public static function createActiveCriteria()
{
return Criteria::create()
->andWhere(Criteria::expr()->eq('active', '1'))
;
}
现在我的想法是在我的 ProductRepository 中使用 Brand Active Criteria 来只获取可见的产品,但前提是品牌是活跃的。所以我的方法现在看起来像这样:
/**
* @param Brand $brand
*
* @return Product[]
*/
public function findAllVisibleForBrand(Brand $brand)
{
return $this->createQueryBuilder('product')
->leftJoin('product.brand', 'brand')
->addCriteria(BrandRepository::createActiveCriteria()) // added this line
->addCriteria(ProductRepository::createVisibleCriteria())
->andWhere('product.brand = :brand')
->setParameter('brand', $brand)
->getQuery()
->execute();
;
}
通过这种方式添加 brandActiveCriteria,我收到以下错误:
[Semantical Error] line 0, col 97 near 'active = :active': Error: Class AppBundle\Entity\Product has no field or association named active
正在构建的查询学说如下所示:
SELECT product FROM
AppBundle\Entity\Product product
LEFT JOIN product.brand brand
WHERE
product.active= :active
AND product.visible = :visible
AND product.brand = :brand
将 table 名称添加到标准中适用于存储库中的查询,但不适用于实体中的查询,因为 table 别名不同。
是否有机会将规则作为标准或在任何其他地方而不重复多个 类?
我想到了使用静态函数来创建标准
https://knpuniversity.com/screencast/collections/criteria-collection-filtering
您可以在条件中添加别名:
public static function createActiveCriteria($alias = null)
{
return Criteria::create()
->andWhere(Criteria::expr()->eq(($alias ? $alias.'.' : '').'active', '1'))
;
}
然后你这样调用你的标准:
// "brand" is the name of the given alias in leftJoin
BrandRepository::createActiveCriteria('brand');
因此您的 findAllVisibleForBrand()
方法将如下所示:
public function findAllVisibleForBrand(Brand $brand)
{
return $this->createQueryBuilder('product')
->leftJoin('product.brand', 'brand')
->addCriteria(BrandRepository::createActiveCriteria('brand')) // Notice the alias parameter here
->addCriteria(ProductRepository::createVisibleCriteria())
->andWhere('product.brand = :brand')
->setParameter('brand', $brand)
->getQuery()
->execute();
;
}
你的 DQL 应该是这样的:
SELECT product FROM
AppBundle\Entity\Product product
LEFT JOIN product.brand brand
WHERE
brand.active= :active
AND product.visible = :visible
AND product.brand = :brand
我已经搜索这个特定问题很长时间了,不确定我是否对在查询中使用 Criteria 有误解,或者它是否不可能(现在?)
这是一个只有最少字段和条件的示例。
我有两个实体:
- 产品
- 字段:可见
- 品牌
- 字段:活动
在品牌实体中,我有一个方法
"getVisibleProducts()"
我想在其中获取所有产品
product.visible = 1
在我的 ProductRepository 中,我有一个方法 findAllVisibleForBrand(Brand $brand)
,我想在其中获取具有 product.visible = 1
和 brand.active = 1
所以我的最佳可重用性想法是为我的 ProductRepository 中的 product.visible
值制定一个标准,并将其用于存储库中的查询
/**
* @param Brand $brand
*
* @return Product[]
*/
public function findAllVisibleForBrand(Brand $brand)
{
return $this->createQueryBuilder('product')
->leftJoin('product.brand', 'brand')
->addCriteria(ProductRepository::createVisibleCriteria())
->andWhere('product.brand = :brand')
->setParameter('brand', $brand)
->getQuery()
->execute();
;
}
/**
* @return Criteria
*/
public static function createVisibleCriteria()
{
return Criteria::create()
->andWhere(Criteria::expr()->eq('visible', '1'))
;
}
在我的品牌实体中:
/**
* @return Product[]|ArrayCollection
*/
public function getVisibleProducts()
{
return $this->getProducts()->matching(ProductRepository::createVisibleCriteria());
}
这工作正常,没有问题。
BrandRepository 的想法相同
/**
* @return Brand[]
*/
public function findAllActiveBrands()
{
return $this->createQueryBuilder('brand')
->addCriteria(BrandRepository::createActiveCriteria())
->getQuery()
->execute()
;
}
/**
* @return Criteria
*/
public static function createActiveCriteria()
{
return Criteria::create()
->andWhere(Criteria::expr()->eq('active', '1'))
;
}
现在我的想法是在我的 ProductRepository 中使用 Brand Active Criteria 来只获取可见的产品,但前提是品牌是活跃的。所以我的方法现在看起来像这样:
/**
* @param Brand $brand
*
* @return Product[]
*/
public function findAllVisibleForBrand(Brand $brand)
{
return $this->createQueryBuilder('product')
->leftJoin('product.brand', 'brand')
->addCriteria(BrandRepository::createActiveCriteria()) // added this line
->addCriteria(ProductRepository::createVisibleCriteria())
->andWhere('product.brand = :brand')
->setParameter('brand', $brand)
->getQuery()
->execute();
;
}
通过这种方式添加 brandActiveCriteria,我收到以下错误:
[Semantical Error] line 0, col 97 near 'active = :active': Error: Class AppBundle\Entity\Product has no field or association named active
正在构建的查询学说如下所示:
SELECT product FROM
AppBundle\Entity\Product product
LEFT JOIN product.brand brand
WHERE
product.active= :active
AND product.visible = :visible
AND product.brand = :brand
将 table 名称添加到标准中适用于存储库中的查询,但不适用于实体中的查询,因为 table 别名不同。
是否有机会将规则作为标准或在任何其他地方而不重复多个 类?
我想到了使用静态函数来创建标准 https://knpuniversity.com/screencast/collections/criteria-collection-filtering
您可以在条件中添加别名:
public static function createActiveCriteria($alias = null)
{
return Criteria::create()
->andWhere(Criteria::expr()->eq(($alias ? $alias.'.' : '').'active', '1'))
;
}
然后你这样调用你的标准:
// "brand" is the name of the given alias in leftJoin
BrandRepository::createActiveCriteria('brand');
因此您的 findAllVisibleForBrand()
方法将如下所示:
public function findAllVisibleForBrand(Brand $brand)
{
return $this->createQueryBuilder('product')
->leftJoin('product.brand', 'brand')
->addCriteria(BrandRepository::createActiveCriteria('brand')) // Notice the alias parameter here
->addCriteria(ProductRepository::createVisibleCriteria())
->andWhere('product.brand = :brand')
->setParameter('brand', $brand)
->getQuery()
->execute();
;
}
你的 DQL 应该是这样的:
SELECT product FROM
AppBundle\Entity\Product product
LEFT JOIN product.brand brand
WHERE
brand.active= :active
AND product.visible = :visible
AND product.brand = :brand