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