与Joins的实体和存储库中的理论可重复使用标准



我很长一段时间搜索了这个特定问题,并且不确定我在查询中使用标准是否有误解,或者是否不可能(尚无法?)

这是一个只有最小字段和条件的示例。

我有两个实体:

  • 产品
    • 字段:可见
  • 品牌
    • 字段:活动

在品牌实体中,我有一种方法 "getVisibleProducts()"我想在哪里获得所有产品 product.visible = 1

,在我的生产中,我有一种方法findAllVisibleForBrand(Brand $brand),我想用product.visible = 1brand.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

相关内容

  • 没有找到相关文章

最新更新