我很长一段时间搜索了这个特定问题,并且不确定我在查询中使用标准是否有误解,或者是否不可能(尚无法?)
这是一个只有最小字段和条件的示例。
我有两个实体:
- 产品
- 字段:可见
- 品牌
- 字段:活动
在品牌实体中,我有一种方法 "getVisibleProducts()"
我想在哪里获得所有产品 product.visible = 1
,在我的生产中,我有一种方法findAllVisibleForBrand(Brand $brand)
,我想用product.visible = 1
和brand.active = 1
因此,我的最佳可重复使用性的想法是在我的productertository中为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'))
;
}
现在,我的想法是使用我的生产商品中的品牌活动标准来获取可见的产品,但只有在品牌活跃的情况下。所以我的方法现在看起来像这样:
/**
* @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();
;
}
通过以这种方式添加品牌侵蚀性,我会收到以下错误:
[语义错误]第0行,col 97接近'Active =:Active':错误:类AppBundle Entity product class AppBundle product没有名为Active
的字段或关联
查询学说正在建造看起来像这样:
SELECT product FROM
AppBundleEntityProduct product
LEFT JOIN product.brand brand
WHERE
product.active= :active
AND product.visible = :visible
AND product.brand = :brand
将表名称添加到存储库中查询的标准工作,而不是在实体内的查询中,因为表别名不相同。
是否有机会将规则作为标准或其他任何地方都有不复制的标准?
?我有使用静态函数创建标准的想法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
AppBundleEntityProduct product
LEFT JOIN product.brand brand
WHERE
brand.active= :active
AND product.visible = :visible
AND product.brand = :brand