对不起,我的英语不好,如果这条消息写错了,我很抱歉 - 这是我的第一个问题。
在过程调用后,我试图解决一个与 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/