1

私の英語で申し訳ありません。このメッセージの構成が間違っていたら申し訳ありません。これが私の最初の質問です。

プロシージャー呼び出しの後、mysql の切断に関する興味深い問題を解決しようとしたとき、私は 2 晩を失いました。さらに興味深いことに、その問題はプロシージャー内の SELECT クエリのみにあると言えます。

だから、私の例。私は2つのクラスと手順を持っています:

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

ええと...「//#LOOK HERE」のように、これらのコードで 2 つのブロックをマークしました - 前に見つけてください。

次のコードを実装する場合...

$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;」というパラメーターを使用したクエリの場合、OK の結果が得られます。

status = 1
status = 1

理解できません - SELECT で PROCEDURE を実行した後、mysql 接続が毎回閉じるのはなぜですか? PROCERUDE の INSERT は問題ありません。助けてください - 私は髪を引き裂いています。

UPD:「if ($stmt->prepare($call) === FALSE) $this->_error();」でエラーが発生する GetData メソッドの。最初の実装は問題ありませんが、残りはすべて悪いです。

4

2 に答える 2

0

ご想像のとおり、この問題は 'mysql' 接続とは関係なく、問題ありませんでした。コードをインストールした後、同様のエラーが発生しました。

ここにすべてのコードがあり、動作します。しかし、多くのデバッグ コードを入れており、現在はかなり乱雑です。

あなたが抱えている主な問題は、「DBConn」クラスにあります。実際の障害は、「store_result」が有効に false を返し、false をエラーとして扱うことです。また、「if」などのすべての「制御フロー ステートメント」では中かっこを使用する必要があるなど、コーディング標準に準拠するようにコードを修正しました。コードを少し再構成して、読みやすくしました。

全体的なロジックはまったく変更していません。

エラーがより明確に表示されるようになりました

PHP 5.3.18 および Windows XP 上の MySQL 5.5.16 で動作しますが、十分にテストされていません。問題があれば投稿してください。それらを整理します。

DBConn クラス:

<?php // 24321955/error-after-calling-mysql-stored-procedures

class DBConn
{
    private $mysqlC = null;

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

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

        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($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)
    {
        //$this->CreateConnection();

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

        if ($stmt->prepare($call) === false) {
            $this->_error(__FILE__.__LINE__, $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(__FILE__.__LINE__, $stmt->errno, $stmt->error);
            }
        }

        if ($stmt->execute() === false) {
            $this->_error(__FILE__.__LINE__, $stmt->errno, $stmt->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)
    {
        $stmt = $this->mysqlC->stmt_init();

        if ($stmt->prepare($call) === false) {
            $this->_error(__FILE__.__LINE__, $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(__FILE__.__LINE__, $stmt->errno, $stmt->error);
            }
        }

        if ($stmt->execute() === false) {
            $this->_error(__FILE__.__LINE__, $stmt->errno, $stmt->error);
        }

        $result = $stmt->store_result();
        if ( $result === false && !empty($stmt->error) ) { // sometimes no result is ok!
            $this->_error(__FILE__.__LINE__, $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();

        //$this->CloseConnection();

        return $arr;
    }
}
于 2014-06-20T17:31:03.307 に答える