Symfony 5+Doctrine 2.10 EAV模式下如何用QueryBuilder实现排序与搜索
方案实现
核心思路
EAV结构下如果需要针对单个属性做排序、搜索条件,需要额外新增一条独立的关联专门对应目标属性,避免和原有拉取多属性的关联逻辑冲突。
1. 按书籍名称属性排序
$qb = $this->createQueryBuilder('book'); $qb // 保留原有拉取所有需要属性的逻辑 ->addSelect([ 'bookAttributeValues', 'bookAttribute', ]) // 注意:你原有代码中的关联属性名是bookAttributeValues,而非attributeValues,这里修正了笔误 ->leftJoin('book.bookAttributeValues', 'bookAttributeValues') ->leftJoin('bookAttributeValues.bookAttribute', 'bookAttribute') ->andWhere( $qb->expr()->in('bookAttribute.handle', [ BookAttribute::NAME, BookAttribute::DESCRIPTION, ]), ) // 新增专门关联NAME属性的属性值,仅用于排序 ->leftJoin( 'book.bookAttributeValues', 'nameSortVal', 'WITH', 'nameSortVal.bookAttribute.handle = :nameHandle' ) ->setParameter('nameHandle', BookAttribute::NAME) // 按名称值正序排序,无名称属性的书籍默认排在末尾,可调整排序方向为DESC ->addOrderBy('nameSortVal.value', 'ASC');
2. 按书籍名称属性值搜索
如果需要只返回名称匹配指定关键词的书籍,实现代码如下:
$qb = $this->createQueryBuilder('book'); // 搜索关键词,前后加%实现模糊匹配,不需要模糊可以去掉 $searchKeyword = '%' . trim($inputKeyword) . '%'; $qb ->addSelect([ 'bookAttributeValues', 'bookAttribute', ]) ->leftJoin('book.bookAttributeValues', 'bookAttributeValues') ->leftJoin('bookAttributeValues.bookAttribute', 'bookAttribute') ->andWhere( $qb->expr()->in('bookAttribute.handle', [ BookAttribute::NAME, BookAttribute::DESCRIPTION, ]), ) // 用innerJoin过滤掉没有名称属性的书籍 ->innerJoin( 'book.bookAttributeValues', 'nameSearchVal', 'WITH', 'nameSearchVal.bookAttribute.handle = :nameHandle' ) // 匹配名称值 ->andWhere($qb->expr()->like('nameSearchVal.value', :searchKeyword)) ->setParameter('nameHandle', BookAttribute::NAME) ->setParameter('searchKeyword', $searchKeyword);
注意事项
你原有代码中存在关联属性名不匹配的笔误:Book实体定义的关联属性是$bookAttributeValues,原有代码中写的book.attributeValues、$book->attributeValues需要对应修改,$value->attribute也要对应修改为$value->bookAttribute,否则会抛出关联不存在的错误。
内容的提问来源于stack exchange,提问作者Denzel Brazhnikoff
相关产品推荐
相关产品推荐

