Symfony2 QueryBuilder return 按 id 顺序查询产品

Symfony2 QueryBuilder return product query in order of ids

我有一个任意顺序的 ID 列表:

array(57, 12, 29, 25, 11)

使用 Symfony 的 QueryBuilder,我只需要 return 这些产品构成所有数据库对象,并且它们应该 return 按此特定顺序编辑。

我需要return查询,而不是结果。

我正在尝试所有不同的方法:

    public function querySortedProductsInCategories($id, $type, $slug, $sort)
    {

        $qb = $this->createQueryBuilder('p');
        $qb->addSelect(array('p', 'gallery'));
        $qb->addSelect(array('p', 'media'));
        $qb->addSelect(array('p', 'image'));
        $qb->leftJoin("p." . $type, "c");
        $qb->leftJoin('p.gallery', 'gallery');
        $qb->leftJoin('gallery.galleryHasMedias', 'media');
        $qb->leftJoin('media.media', 'image');
        $qb->where("c." . $type. "= :id ");
        $qb->andWhere("p.status = 1 ");
        $qb->SetParameter('id', $id);
//        $qb->andWhere($qb->expr()->in('p.id', $sort));
//        $qb->andWhere("p.id IN (:sort) ");
//        $qb->SetParameter('sort', $sort);
        return $qb->getQuery();
    }

我尝试了 IN 语句....它 return 是我需要的列表,但顺序不正确。

现在我开始认为这样做是不可能的。 Whosebug 是我解决这个问题的最后机会...

更新:

试图创建我的 DQL 函数,但出现错误。第一次这样做,我不知道发生了什么......

class Field extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
{

    /**
     * @override
     */
    public function parse(\Doctrine\ORM\Query\Parser $parser) {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->stringPrimary = $parser->StringPrimary();
        $parser->match(Lexer::T_COMMA);
        $this->stringSecondary = $parser->StringPrimary();
        $parser->match(Lexer::T_COMMA);
        $this->stringThird = $parser->StringPrimary();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }


    /**
     * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker
     *
     * @return string
     */
    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        // TODO: Implement getSql() method.
    }

}

查询:

        $em = $this->getEntityManager();
        $doctrineConfig = $em->getConfiguration();
        $doctrineConfig->addCustomStringFunction('FIELD', 'Mp\ShopBundle\Doctrine\Field');

        $qb = $this->createQueryBuilder('p');
        $qb->addSelect(array('p', 'gallery'));
        $qb->addSelect(array('p', 'media'));
        $qb->addSelect(array('p', 'image'));
        $qb->addSelect(array("p, field(p.id, " . implode(", ", $sort) . ") as HIDDEN field"));
        $qb->leftJoin("p." . $type, "c");
        $qb->leftJoin('p.gallery', 'gallery');
        $qb->leftJoin('gallery.galleryHasMedias', 'media');
        $qb->leftJoin('media.media', 'image');
//        $qb->where("p.id = :sort ");
        $qb->where("c." . $type. "= :id ");
        $qb->andWhere($qb->expr()->in('p.id', $sort));
        $qb->andWhere("p.status = 1 ");
        $qb->setParameter('id', $id);
//        $qb->setParameter('sort', $sort);
        $qb->orderBy('field');
        return $qb->getQuery();

错误:

Error: Expected StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression, got '23'

查询:

[1/2] QueryException: SELECT p, p, gallery, p, media, p, image, p, field(p.id, 23, 40, 30, 24, 42, 37, 38, 58, 33, 8, 34, 35, 36, 28, 51, 14, 1) as HIDDEN field FROM Mp\ShopBundle\Entity\Product p LEFT JOIN p.subcategory c LEFT JOIN p.gallery gallery LEFT JOIN gallery.galleryHasMedias media LEFT JOIN media.media image WHERE c.subcategory= :id AND p.id IN(23, 40, 30, 24, 42, 37, 38, 58, 33, 8, 34, 35, 36, 28, 51, 14, 1) AND p.status = 1 ORDER BY field ASC

可按情况下单:

$customOrderString = $this->generateCase($ids);
if(!empty($customOrderString)) {
    $db->addSelect("(CASE {$customOrderString} ELSE 3 END) AS HIDDEN ORD ");
    $db->orderBy('ORD', 'DESC');
}
return $qb->getQuery();

 .....
private generateCase($ids) {
    $caseString = '';
    foreach($ids as $index=>$id) {
        $caseString .= "WHEN $id THEN $index";
    }
    return $caseString;
}

使用 MySQL,您可以创建一个能够使用 FIELD 的 DQL 函数:

查看其他类似问题:

Doctrine 2 mysql FIELD function in order by