【问题标题】:Doctrine DQL dynamic ORDER BY parameterDoctrine DQL 动态 ORDER BY 参数
【发布时间】:2011-09-27 21:42:29
【问题描述】:

我试图将 ORDER BY 列作为 DQL 中的参数传递,如下所示:

$this->em->createQuery("SELECT t FROM Entities\Topic t ORDER BY :order")
     ->setParameters( array('order' => 't.name') )->getResult();

我猜它不起作用,因为 setParameter 会转义 :order,但是下面的解决方案似乎不是很好:

$order = 't.name'; // Dynamic value
$this->em->createQuery("SELECT t FROM Entities\Topic t ORDER BY $order")
     ->getResult();

有没有更好的方法来解决这个问题?

【问题讨论】:

    标签: orm doctrine sql-order-by dql


    【解决方案1】:

    在这种情况下使用教义Querybuilder

    $order = 't.name'; // Dynamic value
    
    $qb = $this->_em->createQueryBuilder();
    $qb->select('t')
       ->from('Entities\Topic', 't')
       ->orderBy($order);
    

    【讨论】:

    • @Dennis 抱歉,如果这个答案伤害了您的感受;)不,说真的 - 如果您有一个动态构建的查询 - 那是查询构建器的真实用例。但另一方面,我认为您的解决方案实际上是可以的。我不会做变量插值,这看起来太不清楚了。如果我是你,就这样做:->createQuery('SELECT t FROM Entities\Topic t ORDER BY ' . $order) 并完成它。
    • @Max,这种方式对 SQL 注入安全吗?!
    • @LucianoMammino 不,您绝对应该有一个允许按值排序的白名单
    • @Max,我刚刚和一个朋友谈过这个话题,他明确指出,最好谈谈“DQL 注入”。无论如何,我们一致认为白名单是这种情况下的最佳解决方案。
    【解决方案2】:

    我知道,这是一个老问题,但直到今天这个“问题”仍然存在。所以,如果你想使用动态排序,你应该使用学说 queryBuilder。

    我最近测试了当前可用于动态排序的学说类型。 就我而言,我在 dql 中设置了 order 列,只想注入 ASC/DESC。

    现在,这是测试输出:

    DQL: SELECT w FROM App\Entity\Worker w ORDER BY w.id :order
    Type "array" is invalid
    Type "ascii_string" is invalid
    Type "bigint" is invalid
    Type "binary" is invalid
    Type "blob" is invalid
    Type "boolean" is invalid
    Type "date" is invalid
    Type "date_immutable" is invalid
    Type "dateinterval" is invalid
    Type "datetime" is invalid
    Type "datetime_immutable" is invalid
    Type "datetimetz" is invalid
    Type "datetimetz_immutable" is invalid
    Type "decimal" is invalid
    Type "float" is invalid
    Type "guid" is invalid
    Type "integer" is invalid
    Type "json" is invalid
    Type "object" is invalid
    Type "simple_array" is invalid
    Type "smallint" is invalid
    Type "string" is invalid
    Type "text" is invalid
    Type "time" is invalid
    Type "time_immutable" is invalid
    

    我正在使用 Symfony 5.3 和 Doctrine 2.9

    如果有人对代码感兴趣,我曾经测试过:我只是在我的 symfony 项目中创建了一个学说实体。然后我在相关的存储库对象中创建了一个测试方法:

    public function testOrder(string $order = 'ASC'): array
    {
        $query = $this->getEntityManager()->createQuery(
            'SELECT w
            FROM App\Entity\Worker w
            ORDER BY w.id :order'
        );
        // map taken from: vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php:101
        $doctrineTypeMap = [
            Types::ARRAY,
            Types::ASCII_STRING,
            Types::BIGINT,
            Types::BINARY,
            Types::BLOB,
            Types::BOOLEAN,
            Types::DATE_MUTABLE,
            Types::DATE_IMMUTABLE,
            Types::DATEINTERVAL,
            Types::DATETIME_MUTABLE,
            Types::DATETIME_IMMUTABLE,
            Types::DATETIMETZ_MUTABLE,
            Types::DATETIMETZ_IMMUTABLE,
            Types::DECIMAL,
            Types::FLOAT,
            Types::GUID,
            Types::INTEGER,
            Types::JSON,
            Types::OBJECT,
            Types::SIMPLE_ARRAY,
            Types::SMALLINT,
            Types::STRING,
            Types::TEXT,
            Types::TIME_MUTABLE,
            Types::TIME_IMMUTABLE,
        ];
        print_r('DQL: ' . $query->getDQL() . "<br/>");
        foreach ($doctrineTypeMap as $mappedType) {
            try {
                $query->setParameter('order', $order, $mappedType);
                print_r('Type "' . $mappedType . '" is ');
                $query->getSQL();
                print_r('valid' . "<br/>");
            } catch (\Exception $e) {
                print_r('invalid' . "<br/>");
            }
        }
        // Prevent symfony from rendering a view
        die();
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 2014-09-14
      • 2019-12-13
      • 2012-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多