【问题标题】:Bind Param with array of parameters将 Param 与参数数组绑定
【发布时间】:2013-04-20 15:00:22
【问题描述】:

我有一个功能可以做到这一点:

function registerUser($firstName, $lastName, $address, $postcode, $email, $password)
{
    $params = array($firstName, $lastName, $address, $postcode, $email, $password);
    $result = $this->db->bind("INSERT INTO Users VALUES (?, ?, ?, ?, ?, ?)", 'ssssss', $params);
}

发送到我的数据库类,它执行以下操作:

public function bind($query, $type, $params)
{
    $this->query = $query;
    $stmt = $this->mysqli->prepare($this->query);
    $stmt->bind_param($type, $param);
    $stmt->execute;
}

问题是这不起作用。

我希望做的是获取$params 列表并让它在$type 之后列出它们,以便查询类似于:

$stmt->bind_param('ssssss', $firstName, $lastName, $address, $postcode, $email, $password);

但显然我的做法是错误的。

有没有办法让数组...按原样转换成要在bind_param 查询阶段打印出来的列表?

【问题讨论】:

  • 您的查询显然是错误的。在 bind_param 之前执行一个 var_dump($this->mysqli->error); 以了解发生了什么问题。

标签: php mysqli bind


【解决方案1】:

call_user_func_array "调用带有参数数组的回调"

call_user_func_array(array($stmt, "bind_param"), array_merge(array($type), $params));

应该做的工作

更新:您还必须更改参数数组:

$params = array(&$firstName, &$lastName, &$address, &$postcode, &$email, &$password);

因为mysqli_stmt::bind_param 需要引用第二个和以下参数。


编辑:您的查询似乎是错误的。也许你的字段比那里的变量少。做:

"INSERT INTO Users (field1, field2, field3, field4, field5, field6) VALUES (?, ?, ?, ?, ?, ?)"

用正确的名称替换字段的名称

【讨论】:

  • 你是对的 - 缺少一个字段。我已经修复了这个但是在使用上面的 call_user_func_array 时,我收到错误“警告:array_merge() [function.array-merge]:参数 #1 不是数组警告:call_user_func_array() 期望参数 2 是数组,给定 null "
  • @DavidG 然后使用array_merge(array($type), $params)。但是当你的$params 没有设置时,我不能做任何事情,因为它应该是正确的。
  • 感谢您的帮助 :) 它几乎可以工作。我收到一个错误:警告:mysqli_stmt::bind_param() 的参数 2 应该是一个参考,给定的值所​​以我会试着弄清楚这是什么
  • @DavidG 嗯,好像你需要在这里做一些eval()...除了第一个参数之外的所有参数都是引用(我不知道为什么...)
  • @DavidG:请参阅this question 了解您的错误消息。并且请不要只在您的陈述前加上@s,它只会抑制错误消息,而不是修复它们的原因。
【解决方案2】:

从 PHP 5.6 开始,您可以利用参数解包作为 call_user_func_array 的替代方法,而且速度通常快 3 到 4 倍。

<?php
function foo ($a, $b) {
     return $a + $b;
}

$func = 'foo';
$values = array(1, 2);
call_user_func_array($func, $values);
//returns 3

$func(...$values);
//returns 3
?>

取自here

所以你的代码应该是这样的:

public function bind($query, $type, $params)
        {

            $this->query = $query;
            $stmt = $this->mysqli->prepare($this->query);
            $stmt->bind_param($type, ...$params);
            $stmt->execute;
        }

【讨论】:

    【解决方案3】:

    您很可能会收到错误“调用非对象上的成员函数 bind_param()”,因为您的 $this->mysqli->prepare 遇到了某种错误。 (请参阅http://php.net/manual/de/mysqli.prepare.php - 它在错误时返回 FALSE,这里似乎就是这种情况)

    在你解决了这个问题之后,试试这个而不是你调用 $stmt->bind_param:

    call_user_func_array(array($stmt, 'bind_param'), array_merge($type, $params));
    

    【讨论】:

      【解决方案4】:

      最简单的方法显然是从 mysqli 切换到 PDO

      它会让你按照你想要的方式去做,甚至不需要任何额外的功能:

      function registerUser($firstName, $lastName, $address, $postcode, $email, $password)
      {
          $sql  = "INSERT INTO Users VALUES (NULL, ?, ?, ?, ?, ?, ?)";
          $stmt = $this->db->prepare($sql);
          $stmt->execute(func_get_args());
      }
      

      【讨论】:

      • @Your Common Sense 你认为 PDO 比 mysqli 更好吗?我也主要使用mysqli,但对PDO了解不多。
      • @Aris 如您所见,PDO 需要的代码大大减少。这两行是你需要的all。不需要额外的绑定功能。 PDO 可以开箱即用
      • 听起来不错。我会尝试在未来使用。我意识到这是一个原生的 php 功能?
      • @Aris 是的,这就是重点。而且 PDO 也有错误报告,所以,你不需要手动检查错误。还有很多其他的事情,比如从查询中得到一个标量,还有很多事情可以让你的代码更好,可读
      【解决方案5】:

      需要注意的是mysqli_stmt_bind_param()要求参数通过引用传递,所以call_user_func_array()的参数必须是引用。取自类上下文的示例:

      function execute( string $query, string $type, array $params )
      {
          if ( !$stmt = $this->mysqli->prepare( $query ) ) 
              throw new \Exception( 'Prepare failed: ' . $query . PHP_EOL . $this->mysqli->error );
      
          // call stmt->bind_param() with variables to bind passed as a reference 
          call_user_func_array( 
              array( $stmt, 'bind_param' ), 
              array_merge( 
                  array( $type ), 
                  array_map( function( &$item ) { return $item; }, $params ) 
              ) 
          );
      
          if ( !$stmt->execute() ) 
              throw new \Exception( 'Execute failed: ' . PHP_EOL . $stmt->error );
      
      }
      
      }
      

      【讨论】:

        【解决方案6】:

        今天,我自己做了一些研究,以创建一种使用准备语句的更短的方法。 @bwoebi 的答案非常有帮助,但不适用于未知数量的参数,因此这是对他答案的补充。

        例如:

        public function bind($query, $type, &...$params)
            {
        
                $this->query = $query;
                $stmt = $this->mysqli->prepare($this->query);
                call_user_func_array(array($stmt, "bind_param"), array_merge([$type], $params));
                $stmt->execute();
            }
        

        使用这个线程: PHP: variable-length argument list by reference?

        我设法将未知数量的参数传递给类中的绑定函数。 然后我使用带有 $type 变量的数组合并的 call_user_func_array(...) 调用绑定参数函数...(必须放在数组内进行合并)

        现在我可以使用 $email 和 $password 来调用这个函数了:

        $myClass->bind($query, "ss", $email, $password);
        

        【讨论】:

          【解决方案7】:

          不漂亮,但我就是这么用的。

          function _BindParam(&$stmt, &$values){
              $types="";
              foreach($values as $val){
                if(is_string($val)){$types.="s";continue;}
                if(is_int($val)){$types.="i";continue;}
                if(is_float($val) || is_double($val)){$types.="d";continue;}
                throw new Exception('Invalid value type');
              }
             $stmt->bind_param($types,...$values);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-29
            • 1970-01-01
            • 2011-09-25
            • 2019-06-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-03
            相关资源
            最近更新 更多