Как использовать параметр внутри строки в Postgres И PHP 5.6?

Как использовать параметр внутри цитаты в Postgres? Я все время получаю ошибку: "SQLSTATE[HY093]: Invalid parameter number: :beginDaysAgo"

Когда мы смотрим на эти строки:

WHERE a.balance <= (a.autorefill_threshold+:amountAboveThreshold)
    AND ((t.created_at <= ( current_timestamp-INTERVAL  \':beginDaysAgo days\')) AND ( t.created_at >= (current_timestamp) - INTERVAL \':totalDays days\'))

Первый параметр не вызывает у меня ошибки. Это те, что внутри цитаты.

Это означает, что первый параметр, amountAboveThreshold, работает, но явно не может выполнять поиск в строке.

По сути, когда я просто использую переменную PHP внутри вместо параметра, она работает отлично, или когда я просто ввожу число. Так, например, когда я помещаю число 20, а затем 21 для этих двух параметров, beginDaysAgo и totalDays соответственно работает отлично.

Но когда я пытаюсь использовать параметры - а это правильный и безопасный способ сделать это - это не работает.

 public function getClientsWithBalanceBelowThreshold(
    $amountAboveThreshold=100.00,
    $beginDaysAgo = 0,
    $amountOfDays = 1
) {

    $totalDays = $amountOfDays + $beginDaysAgo;
    //this one works
    if ((double)$amountAboveThreshold!=$amountAboveThreshold)
        throw new \TypeError("Type Mismatch");
    $conn = $this->em->getConnection();


$conn = $this->em->getConnection();
        $sql = '
          SELECT DISTINCT ON (l.public_id) a.balance, a.public_id as account_public_id, a.organization_name, a.autorefill_threshold,
          l.name  as listing_name, l.paused, l.public_id,
          t.balance_before,
          t.balance_after, t.created_at, t.type
        FROM transaction as t INNER JOIN account a
            ON t.account_id = a.account_id
        INNER JOIN listing as l ON a.account_id = l.account_id
        WHERE a.balance <= (a.autorefill_threshold+:amountAboveThreshold)
        AND ((t.created_at <= ( current_timestamp-INTERVAL  \':beginDaysAgo days\')) AND ( t.created_at >= (current_timestamp) - INTERVAL \':totalDays days\'))
        AND t.balance_before !=  t.balance_after
        AND t.type != \'credit\'
        ORDER BY  l.public_id, a.balance DESC, t.created_at, l.account_id;
        ';
    $stmt = $conn->prepare($sql);
    $stmt->bindParam('amountAboveThreshold', $amountAboveThreshold);
    $stmt->bindParam('beginDaysAgo', $beginDaysAgo);
    $stmt->bindParam('totalDays', $totalDays);
    $stmt->execute();
    var_dump($stmt->fetchAll());die;

Я получаю полную ошибку ...

"SQLSTATE[HY093]: Invalid parameter number: :beginDaysAgo" #0 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/vendor/doctrine/db al/lib/Doctrine/DBAL/Statement.php(141): Doctrine\DBAL\Driver\PDOStatement->bindParam('beginDaysAgo', '18', 2, NULL)
#1 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/src/Rb/ReportingApiBundle/ClientThreshold/ClientBelowThresholdReport.php(77): Doctrine\DBAL\Statement->bindParam('beginDaysAgo', '18')
#2 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/src/Rb/ReportingApiBundle/Command/ClientBelowThresholdReportCommand.php(61): Rb\ReportingApiBundle\ClientThreshold\ClientBelowThresholdReport->getClientsWithBalanceBelowThreshold('120.00', '18', '2')
#3 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/vendor/symfony/symfony/src/Symfony/Component/Console/Command/Command.php(259): Rb\ReportingApiBundle\Command\ClientBelowThresholdReportCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#4 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(863): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#5 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(192): Symfony\Component\Console\Application->doRunCommand(Object(Rb\ReportingApiBundle\Command\ClientBelowThresholdReportCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#6 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(92): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#7 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(123): Symfony\Bundle\FrameworkBundle\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/app/console(29): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput))
#9 {main}

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
86
1

Ответы 1

Я думаю, что когда у вас есть :beginDaysAgo и :totalDays, указанные в запросе, они будут интерпретироваться как буквальные строки, а не как заполнители для параметров. Я бы предложил удалить кавычки и часть days из SQL и оставить только заполнители, например:

(t.created_at <= (current_timestamp - INTERVAL :beginDaysAgo))
AND ( t.created_at >= (current_timestamp - INTERVAL :totalDays))

А затем добавляем часть days к числовым значениям, прежде чем связывать их с подготовленным оператором:

$beginDaysAgo = "$beginDaysAgo days";
$amountOfDays = "$amountOfDays days";

Или, может быть, выполнить конкатенацию в SQL, например, с помощью || (не пробовал)

jcaron 07.05.2018 23:15

@jcaron Да, я думал, что что-то подобное тоже может сработать, но я недостаточно уверен в postgres, чтобы предложить конкретный способ.

Don't Panic 07.05.2018 23:34

Другие вопросы по теме