如何在Postgres和PHP 5.6中使用字符串中的参数?

时间:2018-05-07 19:05:38

标签: php postgresql symfony

如何在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;

我收到的完整错误是......

  

&#34; SQLSTATE [HY093]:参数号无效:: beginDaysAgo&#34;   #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-&gt; bindParam(&#39) ; beginDaysAgo&#39;,&#39; 18&#39;,2,NULL)
  #1 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/src/Rb/ReportingApiBundle/ClientThreshold/ClientBelowThresholdReport.php(77):Doctrine \ DBAL \ Statement-&gt; bindParam(&#39; beginDaysAgo&#39;,& #39; 18&#39;)
  #2 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/src/Rb/ReportingApiBundle/Command/ClientBelowThresholdReportCommand.php(61):Rb \ ReportingApiBundle \ ClientThreshold \ ClientBelowThresholdReport-&gt; getClientsWithBalanceBelowThreshold(&#39; 120.00&#39) ;,&#39; 18&#39;,&#39; 2&#39;)
  #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-&gt; execute(对象(Symfony \ Component \ Console \ Input \ ArgvInput),对象(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-&gt; run(对象(Symfony \ Component \ Console \ Input \ ArgvInput),对象(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-&gt; 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-&gt; doRun(对象(Symfony \ Component \ Console \ Input \ ArgvInput),对象(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-&gt; doRun(对象(Symfony \ Component \ Console \ Input \ ArgvInput),对象(Symfony \ Component \ Console \ Output \ ConsoleOutput))
  #8 /var/www/clientreachapi.com/releases/2018_03_10_14_54_58/app/console(29):symfony \ Component \ Console \ Application-&gt; run(Object(Symfony \ Component \ Console \ Input \ ArgvInput))
  #9 {main}

1 个答案:

答案 0 :(得分:1)

我认为当您在查询中引用:beginDaysAgo:totalDays时,它们将被解释为文字字符串而不是参数的占位符。我建议从SQL中删除引号和days部分,只留下占位符,如下所示:

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

然后将days部分附加到数值,然后再将它们绑定到预准备语句:

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