Symfony2 QueryBuilder按ids

时间:2016-07-28 07:44:12

标签: php mysql symfony query-builder

我有任何顺序的ID列表:

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

使用Symfony的QueryBuilder我只需要从所有数据库对象中返回这些产品,并且应该按照这个特定的顺序返回它们。

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

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

    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语句....它返回了我需要的列表,但输入顺序不正确。

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

更新:

尝试创建我的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.
    }

}

QUERY:

        $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:

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

QUERY:

[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

2 个答案:

答案 0 :(得分:0)

您可以按案件订购:

$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;
}

答案 1 :(得分:0)

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

见另一个类似的问题:

Doctrine 2 mysql FIELD function in order by