Doctrine2 + Symfony2: приведение значений перед привязкой к DQL-запросу

0

Я создаю функцию для фильтрации некоторых записей на основе четырех параметров: $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 LIKE? ИЛИ n0_.anno LIKE? ' с параметрами ["34", 45]:

SQLSTATE [42883]: Неопределенная функция: 7 ERROR: оператор не существует: integer ~~ unknown LINE 1:... dores.norma n0_ WHERE n0_.numero LIKE $ 1 ИЛИ n0_.anno LIKE $ 2 ^ СОВЕТ: Оператор не соответствует указанному имя и аргумент (ы). Возможно, вам придется добавлять явные типы.

Это говорит мне, что мне нужно передать некоторые из этих параметров, прежде чем отправлять их в PgSQL DB и выполнять запрос для получения результатов, но мой вопрос: как я это делаю на Doctrine2 DQL? Возможно? Любое обходное решение или трюк или что-то еще? Я нашел эту документацию, но не знаю, какая функция применяется, а также как, может ли кто-нибудь дать мне какую-нибудь помощь или совет по этому поводу?

Изменить с помощью новых тестов

После предложений пользователей я внесла некоторые изменения в свой код, и теперь он выглядит так:

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 LIKE? ИЛИ n0_.anno LIKE? ' с параметрами ["% 4%", "4"]:

SQLSTATE [42883]: Неопределенная функция: 7 ERROR: оператор не существует: integer ~~ unknown LINE 1:... dores.norma n0_ WHERE n0_.numero LIKE $ 1 ИЛИ n0_.anno LIKE $ 2 ^ СОВЕТ: Оператор не соответствует указанному имя и аргумент (ы). Возможно, вам придется добавлять явные типы.

И как вы можете заметить, в этом случае параметры передаются как должно быть: ["%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 должны быть указаны четыре параметра?

Теги:
doctrine2
doctrine2-postgres

4 ответа

1
Лучший ответ

После глубоких исследований я нашел решение своей проблемы и хочу поделиться с другими. Я должен был сказать также спасибо @ErwinBrandstetter, @b.b3rn4rd за их время и поддержку, а также за @Pradeep, которые в конечном итоге дают мне идею исследования и, наконец, исправили проблему, и я сделал это, включив поддержку неявного литья в PostgreSQL.

Поэтому для включения неявных отбросов вы должны выполнить следующие команды в консоли PostgreSQL при подключении к базе данных template1, чтобы каждая последующая база данных создавала необходимые 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);
}

Счастливое кодирование!

  • 0
    Я бы посоветовал против введения неявных приведений для основных типов , как это. Это может иметь непредвиденные побочные эффекты. Если для базовых типов не определено такое приведение, вероятно, есть веская причина.
  • 0
    @ErwinBrandstetter, это единственный способ, который я нашел для решения проблемы, я уже попробовал все, что вы видите в основном посте и комментариях, возможно, ORM вообще не поддерживает это, или я делаю что-то не так, и я не знаю что еще делать
Показать ещё 4 комментария
1

Ваша первая попытка на самом деле работает для меня все время. Вы можете преобразовать целые числа, используя strval().

'%' . strval($anno) . '%';
  • 0
    Все еще не работает для меня, какая версия PostgreSQL у вас есть? Я использую 9.2.x последний
  • 0
    Во второй попытке, почему вы не добавляете «%» к $ anno? $ qb-> setParameter ('anno', $ anno, PDO :: PARAM_INT);
Показать ещё 10 комментариев
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 || '%'");

В любом другом столбце здесь нет text или varchar? Бросьте это тоже.
Не знаю функцию IDENTITY(). Вывод из Доктрины?
Тем не менее, я не знаю много о Доктрине.

0

Вы пытаетесь использовать LIKE для целого числа, что не имеет смысла.

Переместите целое число в его текстовое представление. Это может сработать:

$qb->where($qb->expr()->like('CAST(n.numero AS text)', ':codigo'));
  • 0
    Это уже попробовано и не сработало, так как я придумала свое решение

Ещё вопросы

Сообщество Overcoder
Наверх
Меню