Я создаю функцию для фильтрации некоторых записей на основе четырех параметров: $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
должны быть указаны четыре параметра?
После глубоких исследований я нашел решение своей проблемы и хочу поделиться с другими. Я должен был сказать также спасибо @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);
}
Счастливое кодирование!
Ваша первая попытка на самом деле работает для меня все время. Вы можете преобразовать целые числа, используя strval().
'%' . strval($anno) . '%';
Я думаю, что в вашей последней попытке необработанная строка 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()
. Вывод из Доктрины?
Тем не менее, я не знаю много о Доктрине.
Вы пытаетесь использовать LIKE
для целого числа, что не имеет смысла.
Переместите целое число в его текстовое представление. Это может сработать:
$qb->where($qb->expr()->like('CAST(n.numero AS text)', ':codigo'));