How can I order by NULL in DQL?

后端 未结 6 747
野趣味
野趣味 2021-01-02 20:18

I\'m building an app using Symfony2 framework and using Doctrine ORM. I have a table with airlines for which some IATA codes are missing. I\'m outputting a list, ordered by

6条回答
  •  独厮守ぢ
    2021-01-02 20:36

    Here it is an example for a custom walker to get exactly what you want. I have taken it from Doctrine in its github issues:

    https://github.com/doctrine/doctrine2/pull/100

    But the code as it is there didn't work for me in MySQL. I have modified it to work in MySQL, but I haven't test at all for other engines.

    Put following walker class for example in YourNS\Doctrine\Waler\ directory;

    getQuery()->getHint('SortableNullsWalker.fields'))
          {
             if (is_array($nullFields))
             {
                $platform = $this->getConnection()->getDatabasePlatform()->getName();
                switch ($platform)
                {
                case 'mysql':
                   // for mysql the nulls last is represented with - before the field name
                   foreach ($nullFields as $field => $sorting)
                   {
                      /**
                       * NULLs are considered lower than any non-NULL value,
                       * except if a – (minus) character is added before
                       * the column name and ASC is changed to DESC, or DESC to ASC;
                       * this minus-before-column-name feature seems undocumented.
                       */
                      if ('NULLS LAST' === $sorting)
                      {
                         $sql = preg_replace_callback('/ORDER BY (.+)'.'('.$field.') (ASC|DESC)/i', function($matches) {
                            if ($matches[3] === 'ASC') {
                               $order = 'DESC';
                            } elseif ($matches[3] === 'DESC') {
                               $order = 'ASC';
                            }
                            return ('ORDER BY -'.$matches[1].$matches[2].' '.$order);
                         }, $sql);
                      }
                   }
                      break;
                case 'oracle':
                case 'postgresql':
                   foreach ($nullFields as $field => $sorting)
                   {
                      $sql = preg_replace('/(\.' . $field . ') (ASC|DESC)?\s*/i', "$1 $2 " . $sorting, $sql);
                   }
                   break;
                default:
                   // I don't know for other supported platforms.
                   break;
                   }
                }
             }
    
             return $sql;
       }
    }
    

    Then:

    use YourNS\Doctrine\Walker\SortableNullsWalker;
    use Doctrine\ORM\Query;
    
    [...]
    
    $qb = $em->getRepository('YourNS:YourEntity')->createQueryBuilder('e');
    $qb
       ->orderBy('e.orderField')
       ;
    
    $entities = $qb->getQuery()
      ->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER,  '\YourNS\Doctrine\Walker\SortableNullsWalker')
      ->setHint('SortableNullsWalker.fields', array(
         'sortOrder' => SortableNullsWalker::NULLS_LAST
      ))
      ->getResult();
    

提交回复
热议问题