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

Я строю функцию для фильтрации некоторых записей на основе четырех параметров: $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 figurero0,
n0_.anno AS anno1, n0_.id AS id2, n0_.nombre AS nombre3, n0_.activo AS
activo4, n0_.comite_tecnico_id AS comite_tecnico_id5 ОТ
nomencladores.norma n0_ ГДЕ n0_.numero НРАВИТСЯ? ИЛИ n0_. Не нравится?
с параметрами [«34», 45]:

SQLSTATE [42883]: неопределенная функция: 7 ОШИБКА: оператор не существует:
целое число ~~ неизвестно ЛИНИЯ 1: … dores.norma n0_ ГДЕ n0_.numero LIKE $ 1
ИЛИ n0_.anno LIKE $ 2 ^ СОВЕТ: ни один оператор не соответствует указанному имени и
Тип аргумента (ов). Возможно, вам понадобится добавить явное приведение типов.

Это говорит мне о том, что мне нужно привести некоторые из этих параметров перед тем, как отправить их в базу данных PgSQL и выполнить запрос, чтобы получить результаты, но мой вопрос в том, как мне это сделать на 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 figurero0,
n0_.anno AS anno1, n0_.id AS id2, n0_.nombre AS nombre3, n0_.activo AS
activo4, n0_.comite_tecnico_id AS comite_tecnico_id5 ОТ
nomencladores.norma n0_ ГДЕ n0_.numero НРАВИТСЯ? ИЛИ n0_. Не нравится?
с параметрами [«% 4%», «4»]:

SQLSTATE [42883]: неопределенная функция: 7 ОШИБКА: оператор не существует:
целое число ~~ неизвестно ЛИНИЯ 1: … dores.norma n0_ ГДЕ n0_.numero LIKE $ 1
ИЛИ n0_.anno LIKE $ 2 ^ СОВЕТ: ни один оператор не соответствует указанному имени и
Тип аргумента (ов). Возможно, вам понадобится добавить явное приведение типов.

И, как вы можете заметить, в этом случае параметры передаются так, как должно быть: ["%4%", "4"] но почему ошибка? Все еще не добираюсь, где это

Еще один тест

Итак, знакомясь с Doctrine Query Builder и применяя некоторый Doctrine Query Language, я переместил запрос из кода выше в этот:

    $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 должно быть четыре параметра требуется?

0

Решение

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

'%' . strval($anno) . '%';
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);
}

Удачного кодирования!

1

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

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

$qb->where($qb->expr()->like('CAST(n.numero AS text)', ':codigo'));
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
По вопросам рекламы [email protected]