Doctrine2 + Symfony2:在绑定到DQL查询之前转换值

时间:2014-11-11 01:46:54

标签: php postgresql symfony doctrine-orm doctrine-orm-postgres

我正在建立一个功能,根据以下四个参数过滤一些记录:$codigo$anno$term$comite_tecnico。这是我到现在为止所建立的:

public function filtrarNorma($codigo = null, $anno = null, $term = null, $comite_tecnico = null)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
            ->select('n')
            ->from("AppBundle:Norma", "n");

    if ($codigo != NULL) {
        $qb->where($qb->expr()->like('n.numero', ':codigo'));
        $qb->setParameter('codigo', '%' . $codigo . '%');
    }

    if ($anno != NULL) {
        $qb->orWhere($qb->expr()->like('n.anno', ':anno'));
        $qb->setParameter('anno', '%' . $anno . '%');
    }

    if ($term != NULL) {
        $qb->orWhere($qb->expr()->like('n.nombre', ':term'));
        $qb->setParameter('term', '%' . $term. '%');
    }

    if ($comite_tecnico != NULL) {
        $qb->orWhere($qb->expr()->like('n.comite_tecnico', ':comite_tecnico'));
        $qb->setParameter('comite_tecnico', '%' . $comite_tecnico . '%');
    }

    return $qb->getQuery()->getResult();
}

每当我尝试执行查询时,都会收到此错误:

  

执行' SELECT n0_.numero AS numero0时发生异常,   n0_.anno AS anno1,n0_.id AS id2,n0_.nombre AS nombre3,n0_.activo AS   activo4,n0_.comite_tecnico_id AS comite_tecnico_id5 FROM   nomencladores.norma n0_ WHERE n0_.numero喜欢?或者n0_.anno喜欢?'   与params [" 34",45]:

     

SQLSTATE [42883]:未定义的函数:7 ERROR:运算符不存在:   整数~~未知LINE 1:... dores.norma n0_ WHERE n0_.numero LIKE $ 1   或者n0_.anno LIKE $ 2 ^提示:没有运算符匹配给定的名称和   参数类型。您可能需要添加显式类型转换。

告诉我在将它们发送到PgSQL数据库并执行查询以获得结果之前我需要先抛出其中的一些参数但我的问题是,我是如何在Doctrine2 DQL上执行此操作的?可能吗?任何变通方法或技巧或其他东西?我找到了this文档,但不知道哪些功能适用,以及如何,可以给我一些帮助或建议吗?

使用新测试进行编辑

在用户建议后,我对我的代码进行了一些更改,现在看起来像是:

public function filtrarNorma($codigo = null, $anno = null, $term = null, $comite_tecnico = null)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
            ->select('n')
            ->from("AppBundle:Norma", "n");

    if ($codigo != NULL) {
        $qb->where($qb->expr()->like('n.numero', ':codigo'));
        $qb->setParameter('codigo', '%'.$codigo.'%', PDO::PARAM_STR);
    }

    if ($anno != NULL) {
        $qb->orWhere($qb->expr()->like('n.anno', ':anno'));
        $qb->setParameter('anno', $anno, PDO::PARAM_INT);
    }

    if ($term != NULL) {
        $qb->orWhere($qb->expr()->like('n.nombre', ':term'));
        $qb->setParameter('term', '%'.$term.'%', PDO::PARAM_STR);
    }

    if ($comite_tecnico != NULL) {
        $qb->orWhere($qb->expr()->like('IDENTITY(n.comite_tecnico)', ':comite_tecnico'));
        $qb->setParameter('comite_tecnico', '%'.$comite_tecnico.'%', PDO::PARAM_INT);
    }

    return $qb->getQuery()->getResult();
}

但是再一次,得到同样的错误:

  

执行' SELECT n0_.numero AS numero0时发生异常,   n0_.anno AS anno1,n0_.id AS id2,n0_.nombre AS nombre3,n0_.activo AS   activo4,n0_.comite_tecnico_id AS comite_tecnico_id5 FROM   nomencladores.norma n0_ WHERE n0_.numero喜欢?或者n0_.anno喜欢?'   与params ["%4%"," 4"]:

     

SQLSTATE [42883]:未定义的函数:7 ERROR:运算符不存在:   整数~~未知LINE 1:... dores.norma n0_ WHERE n0_.numero LIKE $ 1   或者n0_.anno LIKE $ 2 ^提示:没有运算符匹配给定的名称和   参数类型。您可能需要添加显式类型转换。

正如你可能会注意到在这种情况下,params传递的应该是:["%4%", "4"],但为什么会出错呢?仍然没有得到它的地方

另一项测试

因此,借助Doctrine Query Builder并应用一些Doctrine查询语言,我将查询从上面的代码移到了这个:

    $em = $this->getEntityManager();
    $query = $em->createQuery("SELECT n from AppBundle:Norma n WHERE n.numero LIKE '%:codigo%' OR n.anno LIKE '%:anno%' OR n.nombre LIKE '%:term%' OR IDENTITY(n.comite_tecnico) LIKE '%:comite_tecnico%'");
    $query->setParameters(array(
            'codigo' => $codigo,
            'anno' => $anno,
            'term' => $term,
            'comite_tecnico' => $comite_tecnico
        ));

    return $query->getResult();

但在这种情况下,我收到了这条消息:

  

参数号无效:绑定变量数不匹配   令牌数量

如果查询是由OR进行的,那么应该是所需的四个参数吗?

4 个答案:

答案 0 :(得分:1)

你的第一次尝试实际上对我有效。您可以使用strval()'。

转换整数
'%' . strval($anno) . '%';

答案 1 :(得分:1)

经过深入研究后,我找到了解决问题的方法,并希望与其他人分享。我还应该感谢@ErwinBrandstetter,@ b.b3rn4rd的时间和支持以及@Pradeep最终给了我研究的想法并最终解决了问题我通过在PostgreSQL中启用隐式转换支持来做到了。

为了启用隐式转换,您必须在连接到template1数据库时在PostgreSQL控制台中执行以下命令,以便之后创建的任何数据库都将附带所需的CAST(如果已创建数据库,则执行数据库中的命令也是如此):

CREATE FUNCTION pg_catalog.text(integer) RETURNS text STRICT IMMUTABLE LANGUAGE SQL AS 'SELECT textin(int4out($1));';
CREATE CAST (integer AS text) WITH FUNCTION pg_catalog.text(integer) AS IMPLICIT;
COMMENT ON FUNCTION pg_catalog.text(integer) IS 'convert integer to text';

CREATE FUNCTION pg_catalog.text(bigint) RETURNS text STRICT IMMUTABLE LANGUAGE SQL AS 'SELECT textin(int8out($1));';
CREATE CAST (bigint AS text) WITH FUNCTION pg_catalog.text(bigint) AS IMPLICIT;
COMMENT ON FUNCTION pg_catalog.text(bigint) IS 'convert bigint to text';

这就是全部,在我正在使用的当前数据库上运行之后,在template1上运行以后的数据库并保持条件如下所示,一切正常并且没有任何错误:

if ($codigo != null) {
    $qb->where($qb->expr()->like('n.numero', ':codigo'));
    $qb->setParameter('codigo', '%'.$codigo.'%', PDO::PARAM_STR);
}

if ($anno != null) {
    $qb->orWhere($qb->expr()->like('n.anno', ':anno'));
    $qb->setParameter('anno', '%'.$anno.'%', PDO::PARAM_STR);
}

if ($term != null) {
    $qb->orWhere($qb->expr()->like('n.nombre', ':term'));
    $qb->setParameter('term', '%'.$term.'%', PDO::PARAM_STR);
}

if ($comite_tecnico != null) {
    $qb->orWhere($qb->expr()->like('IDENTITY(n.comite_tecnico)', ':comite_tecnico'));
    $qb->setParameter('comite_tecnico', '%'.$comite_tecnico.'%', PDO::PARAM_STR);
}

快乐的编码!!

答案 2 :(得分:0)

您尝试在整数上使用LIKE,这是没有意义的。

将整数转换为其文本表示形式。这可能有效:

$qb->where($qb->expr()->like('CAST(n.numero AS text)', ':codigo'));

答案 3 :(得分:0)

我认为在您上次尝试时,原始SQL字符串应如下所示:

$query = $em->createQuery("SELECT n.*
    FROM  nomencladores.norma n
    WHERE n.numero LIKE '%' || :codigo || '%' OR
          cast(n.anno AS text) LIKE '%' || :anno || '%' OR
          n.nombre LIKE '%' || :term || '%' OR
          IDENTITY(n.comite_tecnico) LIKE '%' || :comite_tecnico || '%'");

此处的任何其他列都不是textvarchar?也把它投下来。
不知道IDENTITY()功能。来自学说的溢出效应也是如此? 不过,我对Doctrine一无所知。