用php7.0编程一个动态调用mysql存储过程的函数

时间:2018-03-08 08:36:27

标签: php mysql stored-procedures

只需几句话来解释我想做什么。

我想用能够调用存储过程的函数扩展我的lib。我在这里找到了制作它的步骤,但我很难将其设为泛型

为了达到这个目的,我已经读过我必须在mysqli_stmt_bind_param上使用call_user_func_array,因为我只知道执行时参数IN的数量,类型和OUT的数量

以下是我所做的一些细节:

  • 创建与DB的连接
  • 设置字符集
  • 构建调用字符串,例如CALL(?,?,?,@ outParam1,@ outParam2)
  • 准备调用字符串
  • 构建一个与call_user_func_array一起使用的参数数组,它将调用mysqli_stmt_bind_param< =这会给我带来麻烦
  • 调用mysql_stmt_excute
  • 最后,做一个选择以获取参数。

这里是代码的主要部分:

function executeProc($sProcName, $sInParamTypes, $aInParam, $iNumberParameterOut=0)
{
  $oConnection = @mysqli_connect(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DBNAME);

  mysqli_set_charset($oConnection, "utf8");

  /* code to build the $sCallStr */

  $oMysqlCall = mysqli_prepare($oConnection, $sCallStr);

  array_unshift($aFunctionParam, $oMysqlCall, $sInParamTypes);

  $aFunctionParam = array_merge($aFunctionParam, $aInParam);

  call_user_func_array("mysqli_stmt_bind_param", $aFunctionParam);

  mysqli_stmt_execute($oMysqlCall);
}

call_user_func_array的返回值为NULL。我试着把这个函数称为manualy:

 mysqli_stmt_bind_param($aFunctionParam[0], $aFunctionParam[1], $aFunctionParam[2], $aFunctionParam[3], $aFunctionParam[4], $aFunctionParam[5], $aFunctionParam[6], $aFunctionParam[7]);

它有效。我在DB中看到结果,并且函数的返回为TRUE。 有人可以帮忙吗?是否有另一种传递参数数组的方法? (比如参考?)

非常感谢您的帮助

2 个答案:

答案 0 :(得分:0)

您可以使用...使用"Argument unpacking"

mysqli_stmt_bind_param($oMysqlCall, $sInParamTypes, ...$aInParam);

这适用于引用传递的变量,无需使用array_unshift()array_merge()来构建参数。

示例:

function foo(&$a, &$b, &$c) { var_dump($a,$b,$c); }

这将有效:

$arr = [1,2,3];
foo(...$arr); // Works

但这会产生警告:

$arr = [1,2,3];
call_user_func_array('foo', $arr); 
// Warning:  Parameter 1 to foo() expected to be a reference, value given

答案 1 :(得分:0)

以下是对我的问题的反馈:

我已经在您的帮助和帖子https://stackoverflow.com/a/48128540/6050817的帮助下完成了我的功能,并且效果很好。

我想发布我要分享的complet代码。此函数执行存储过程并收集此过程选择的所有数据和所有输出参数

function executeProc($sProcName, $sInParamTypes = "", $aInParam = null, $iNumberParameterOut=0)
{
  global $oError;
  $oError = false;
  $aRows = array();
  $sCallStr = "";
  $sSelectOutParam = "";
  $aReturn = array();

  if($aInParam == null)
  {
    $aInParam = array();
  }

  $iLevel = error_reporting(9);

  // open connection to DB
  $oConnection = @mysqli_connect(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DBNAME);
  if ($oConnection === false)
  {
    $oError = mysqli_error($oConnection);
    return false;
  }
  // we set the character set
  mysqli_set_charset($oConnection, "utf8");


  // we build the call to the stored procedure
  $sCallStr = "CALL ";

  $sCallStr =  $sCallStr.$sProcName."(";

  // we add the IN parameters
  foreach($aInParam AS $sParam)
  {
    $sCallStr =  $sCallStr."?,";
  }

  // we add the OUT parameters (since we can't access directly the out parameters, we store their value in variables @ on the DB) we will access theme at the end
  for($iIndex=0; $iIndex<$iNumberParameterOut; $iIndex++)
  {
    $sSelectOutParam = $sSelectOutParam."@outParam".$iIndex.",";
  }

  // we remove the unwanted coma
  if($iNumberParameterOut > 0)
  {
    $sSelectOutParam = rtrim($sSelectOutParam, ",");
  }
  else
  {
    $sCallStr =  rtrim($sCallStr, ",");
  }

  // we merge the two parameters string and add the final parenthesis
  $sCallStr = $sCallStr.$sSelectOutParam.")";

  // we prepare the call
  $oMysqlCall = mysqli_prepare($oConnection, $sCallStr);

  // only if we have parameters we bind the call with the types and the list of IN parameters. If no parameters is waited by the stored procedure we don't need to bind
  if(count($aInParam) > 0)
  {
    mysqli_stmt_bind_param($oMysqlCall, $sInParamTypes, ...$aInParam);
  }

  // we execute the stored procedure
  mysqli_stmt_execute($oMysqlCall);

  // we get the data that would be returned by select in the procedure
  while ($oResult = mysqli_stmt_get_result($oMysqlCall)) 
  {
    if (mysqli_num_rows($oResult) > 0) 
    {
      while ($oRow = mysqli_fetch_assoc($oResult)) 
      {
        foreach($oRow as $key => $val) 
        {
          $aRows[$key] = $val;
        }
        $aReturn[] = $aRows;
        $aRows = array();
      }
    }

    // we free the return variable
    mysqli_free_result($oResult);  

    // we get the next return
    mysqli_stmt_next_result($oMysqlCall);
  }

  // we have to close the call to get the out parameters
  mysqli_stmt_close($oMysqlCall);

  if($iNumberParameterOut > 0)
  {
    // to get the out parameters stored in variables we have to make a select on on the DB
    $oResult = mysqli_query($oConnection, "SELECT ".$sSelectOutParam.";");

    // for every variable we create a row and add to an array
    for($iIndex=0; $iIndex<$iNumberParameterOut; $iIndex++)
    {
      $iReturnIndex = 0;
      while($oRow = mysqli_fetch_assoc($oResult))
      {
        if ($oRow===false) $oRow = array();
        $aRows[key($oRow)] = $oRow[key($oRow)];
        $iReturnIndex++;
      }
      if ($oRow===false && $iReturnIndex==0)
      {
        $aRows[0] = array();
      }
    }
    // stored in the out key of our main return variable
    $aReturn["out"] = $aRows;
  }

  // we free the rest 
  mysqli_free_result($oResult);
  mysqli_close($oConnection);

  error_reporting($iLevel);

  // and return the data
  return $aReturn;
}

}

希望这能有所帮助。随意评论或询问您是否理解某事