php - 调用mysql存储过程后报错

标签 php mysql call procedure disconnected

对不起,我的英语不好,如果这条消息写错了,我很抱歉 - 这是我的第一个问题。

在过程调用后,我试图解决一个与 mysql 断开连接有关的有趣问题,我已经浪费了 2 个晚上的时间。这会更有趣,我会说,这个问题只与过程中的 SELECT 查询有关。

所以,我的例子。我有 2 个类(class)和程序:

1) DBCONN - 用于连接和处理查询。

class DBCONN
{
    private $mysqlC = null;

    public function __construct()
    {
        $this->CreateConnection();
    }

    public function __destruct() 
    {
        //$this->mysqlC->close();
    }

    private function CreateConnection()
    {
        $mC = new mysqli("localhost", "root", "root", "root");

        if ($mC->connect_error)
            die('Bye. '.$mC->connect_errno."-".$mC->connect_error);
        else 
            $mC->set_charset("utf8");

        $this->mysqlC = $mC;
    }

    private function CloseConnection()
    {
        $this->mysqlC->close();
    }

    private function _error()
    {
        die('Bye. '.$this->mysqlC->connect_errno."-".$this->mysqlC->connect_error);
    }

    public function SetData($call, $types = null, $params = null)
    {
        //$this->CreateConnection();

        $stmt = $this->mysqlC->stmt_init();

        if ($stmt->prepare($call) === FALSE) 
            $this->_error();

        if ($params && call_user_func_array(array($stmt, "bind_param"),     array_merge(array($types), $params)) === FALSE)
            $this->_error();
        if ($stmt->execute() === FALSE) 
            $this->_error();

        $insid = $stmt->insert_id;
        $affrows = $stmt->affected_rows;

        $stmt->close();

        //$this->CloseConnection();

        return array($insid, $affrows);
    }

    public function GetData($call, $types = null, $params = null)
    {
        //$this->CreateConnection();
        //#LOOK HERE BEGIN
        print 'status = '.$this->mysqlC->ping();
        //#LOOK HERE END
        //print $call;

        $stmt = $this->mysqlC->stmt_init();

        if ($stmt->prepare($call) === FALSE) 
            $this->_error();

        if ($params && call_user_func_array(array($stmt, "bind_param"), array_merge(array($types), $params)) === FALSE)
            $this->_error();

        if ($stmt->execute() === FALSE) 
            $this->_error();
        if ($stmt->store_result() === FALSE) 
            $this->_error();

        $meta = $stmt->result_metadata();

        while ($field = $meta->fetch_field())
             $var[] = &$row[$field->name];

        call_user_func_array(array($stmt, 'bind_result'), $var);

        $arr = null;

        while ($stmt->fetch())
        {
            foreach($row as $key => $val)
                $c[$key] = $val;

            $arr[] = $c;
        }

        $stmt->close();

        //$this->CloseConnection();

        return $arr;        
    }

}

2) BASEACTIONS - 创建 DBCONN 对象并向其发送文本命令。

class BASEACTIONS
{
    private $conn = null;
    public function __construct() {
        $this->conn = new DBCONN();
    }

    private function CheckPassword($email = '', $pass = '')
    {
        //#LOOK HERE BEGIN
        $arr = $this->conn->GetData("CALL Login_Actions(-1, '$email', '', '$pass', '');"); 
        $arr = $this->conn->GetData("CALL Login_Actions(-1, '$email', '', '$pass', '');");
        //#LOOK HERE END

        return ($arr[0]['isTrue']==1 ? true : false);
    }

    private function UpdateSession($email)
    {
        if (!session_regenerate_id()) return false;
        $session = session_id();

        $this->conn->SetData(
            "CALL Login_Session(2, ?, ?)",
            "ss", 
            array(&$email, &$session)
        );

        return true;
    }


    public function LoginUser($email = '', $pass = '')
    {
        if (!$this->UpdateSession($email)) return false;
        if (!$this->CheckPassword($email, $pass)) return false;

        return true;
    }
}

3) 存储过程

CREATE DEFINER=`root`@`localhost` PROCEDURE `Login_Actions`(
_action INT, 
_vcEmail varchar(50),
_vcNickname varchar(20),
_vcPassword varchar(255),
_vcPasssalt varchar(10)
)
BEGIN

case _action
    when -1 then
        select md5(concat(md5(_vcPassword), vcPasssalt)) = vcPassword 'isTrue' from Login where vcEmail=_vcEmail;
    when 0 then
        select iId, vcEmail, vcNickname from Login;
    when 1 then
        insert into Login(vcEmail, vcNickname, dtDateAdd, vcPassword, vcPasssalt) values(_vcEmail, _vcNickname, UTC_TIMESTAMP(), md5(concat(md5(_vcPassword), _vcPasssalt)), _vcPasssalt);
end case;

END

好吧...我在这些代码中为您标记了 2 个 block ,例如“//#LOOK HERE” - 请先找到它。

如果你要实现下一个代码...

$BASE = new BASEACTIONS();
$BASE->LoginUser("mail@mail.com", "mypassword");

...页面将返回给您

status = 1
status = Bye. 0-

但是如果你要改变“CALL Login_Actions(-1, '$email', '', '$pass', '');”在使用这些参数“select md5(concat(md5($pass), vcPasssalt)) = vcPassword 'isTrue' from Login where vcEmail=$email;”查询 which case procedure 时,你会得到 OK 结果。

status = 1
status = 1

我不明白 - 为什么每次使用 SELECT 执行 PROCEDURE 后 mysql 连接都会关闭? PROCERUDE 中的 INSERT 没有问题。请帮帮我 - 我的头发都快撕裂了。

更新:错误发生在“if ($stmt->prepare($call) === FALSE) $this->_error();” GetData 方法。第一次实现还可以,其他都不好。

最佳答案

我找到了一些解决方案。它不是很漂亮,但它可以工作并有助于解决在 1 个连接中调用多个过程的问题。

我需要在我的 GetData 方法中添加这一行。

$stmt->close();
while(mysqli_more_results($this->mysqlC))  //<<<<---- this line
    mysqli_next_result($this->mysqlC); //<<<<---- this line

return $arr;

所以,最后一节课是:

class DBConn
{
private $mysqlC = null;

public function __construct()
{
    $mC = new mysqli("localhost", "user", "password", "database");

    if ($mC->connect_error)
        $this->Error("Bye. ", $mC->connect_errno, $mC->connect_error);
    else
        $mC->set_charset("utf8");

    $this->mysqlC = $mC;
}

public function __destruct()
{
    $this->mysqlC->close();
}

private function IsConnected()
{
    return $this->mysqlC->ping();
}

private function Error($msg = '', $errno = 0, $error = '')
{
    die("Bye. {$msg} ".
               ($errno != 0 ? "errno: {$errno} - {$error}"
                            : "errno: {$this->mysqlC->errno} - {$this->mysqlC->error}"));
}

public function SetData($call, $types = null, $params = null)
{
    $stmt = $this->mysqlC->stmt_init();

    if ($stmt->prepare($call) === false) {
        $this->Error("", $stmt->errno, $stmt->error);
    }

    if ($params) {
        $result = call_user_func_array(array($stmt, "bind_param"),
                                              array_merge(array($types), $params));
        if ($result === false) {
            $this->Error("", $stmt->errno, $stmt->error);
        }
    }

    if ($stmt->execute() === false) {
        $this->Error("", $stmt->errno, $stmt->error);
    }

    $insid = $stmt->insert_id;
    $affrows = $stmt->affected_rows;

    $stmt->close();

    return array($insid, $affrows);
}

public function GetData($call, $types = null, $params = null)
{
    $stmt = $this->mysqlC->stmt_init();

    if ($stmt->prepare($call) === false) {
        $this->Error("", $stmt->errno, $stmt->error);
    }

    if ($params) {
        $result = call_user_func_array(array($stmt, "bind_param"),
                                       array_merge(array($types), $params));
        if ($result === false) {
            $this->Error("", $stmt->errno, $stmt->error);
        }
    }

    if ($stmt->execute() === false) {
        $this->Error("", $stmt->errno, $stmt->error);
    }

    $result = $stmt->store_result();
    if ( $result === false && !empty($stmt->error) ) { // failing!!! and throw away result
        $this->Error("", $stmt->errno, $stmt->error);
    }

    $meta = $stmt->result_metadata();

    while ($field = $meta->fetch_field()) {
         $var[] = &$row[$field->name];
    }

    call_user_func_array(array($stmt, 'bind_result'), $var);

    $arr = null;

    while ($stmt->fetch()) {
        foreach($row as $key => $val)
            $c[$key] = $val;

        $arr[] = $c;
    }

    $stmt->close();
    while(mysqli_more_results($this->mysqlC))  //<<<<---- this line
        mysqli_next_result($this->mysqlC); //<<<<---- this line

    return $arr;
}
}

谢谢大家,极客们!

关于php - 调用mysql存储过程后报错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24321955/

相关文章:

javascript - addEventListener - 指定带有属性的函数引用

Java如何调用另一个类?

function - CUDA C++ 中的一个函数调用另一个函数

php - 我可以订购 Joomla 错误信息吗?

Php MySQL更新html表单

Mysql 左外连接不包括左表中的所有记录

PHP/MySQL : How to reduce code to echo Select results (working code)

php - 加载iframe(谷歌地图)存储在从mysql加载到链接div中的变量中

php - 上传的图片没有出现在网络上

php - 使用php将字符串转换为逗号分隔的数组