Search code examples
symfonydoctrine-ormdoctrine-query

Query Builder "OR" in dynamic query


I would like to build a query with clause "OR" and the query receive an array parameter and doesn't know how elements it contains.

The query has to return a list of contents that have the category "1" or "2"(if $categ array contain [1,2]) etc. Category is a foreign key in the content entity.

My repository:

   public function getContentOfSomeCategories($categs)
    {
        $query = $this->createQueryBuilder('c');

        $conditions = [];
        foreach($categs as $value){
            $conditions[] = 'c.contentCategory = '.$value;
        }

        $orX = $query->expr()->orX();
        foreach ($conditions as $condition) {
            $orX->add($condition);
        }
        $query->add('where', $orX);

I obtain the error message "Too many parameters: the query defines 1 parameters and you bound 2".


Solution

  • From PHP 5.6 onward, you can probably use PHP splat ... to expand an array to arguments.

            $query = $this->createQueryBuilder('c');
            $expr = $query->expr();
    
            $conditions = [];
            $valueNo = 0;
            foreach ($categs as $value) {
                $conditions[] = $expr->eq('c.contentCategory', 'value'.$valueNo);
                $query->setParameter('value'.$valueNo, $value);
                $valueNo++;
            }
            $query->andWhere($expr->orX(...$conditions));
    

    Disclaimer: I've not tested this.

    See: https://www.php.net/manual/en/functions.arguments.php

    You can also use ... when calling functions to unpack an array or Traversable variable or literal into the argument list:

    Edit:

    If your query is simple, you could just use orWhere instead.

            $query = $this->createQueryBuilder('c');
            $expr = $query->expr();
    
            $valueNo = 0;
            foreach ($categs as $value) {
                $query->orWhere($expr->eq('c.contentCategory', 'value'.$valueNo));
                $query->setParameter('value'.$valueNo, $value);
                $valueNo++;
            }
    

    Edit 2:

    You might even want to just use an in clause instead.

    $query->where($expr->in('c.contentCategory', ':values'));
    $query->setParameter('values', $categs);`