![](/img/trans.png)
[英]PHP Warning: print_r and debug_backtrace when passing a mysqli connection
[英]PHP print_r clears status from a mysqli connection object?
我有一个MySQL表,其中需要三列,每个列在表中是唯一的,分别是userName,userEmail和userUID。 对于这些列中的每列,都使用UNIQUE设置了该表。 为了防止出现竞争情况,我尝试插入一个新用户,然后选择“重复输入”错误,分析错误消息以确定哪一列出了问题,然后向用户询问新信息。 我正在尝试调试此代码,并在对重复的列名称进行任何测试之前,放置了print_r($dbConn, true)
以捕获INSERT语句的结果。 这使事情变得很errno
,因为它似乎消除了mysqli连接对象中的errno
和error
值。 以下是说明问题的样本:
<?php
error_reporting(E_ALL);
echo 'PHP Version: ' . phpversion() . PHP_EOL;
$dbConn = @new mysqli('127.0.0.1', 'userX', 'passwordX', 'databaseX');
$dbConn->query('CREATE TABLE IF NOT EXISTS print_r_test (' .
'username VARCHAR(64), UNIQUE (username)');
echo 'Created print_r_test table.' . PHP_EOL;
$dbConn->query('TRUNCATE TABLE print_r_test');
echo 'Truncated print_r_test table.' . PHP_EOL;
$dbConn->query('INSERT INTO print_r_test (username) VALUES (\'testuser\')');
echo '' . 'INSERT#1: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
// This next one fails with duplicate entry 'testuser' for 'username'
$dbConn->query('INSERT INTO print_r_test (username) VALUES (\'testuser\')');
// echo '$dbConn: ' . print_r($dbConn, true) . PHP_EOL;
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
?>
请注意,第14行已被注释掉。
如果按原样运行(更改了userX,passwordX和databaseX之后),它将按预期运行:
H:>php print_r_test2.php
PHP Version: 5.4.10
Created print_r_test table.
Truncated print_r_test table.
INSERT#1: 0:
INSERT#2: 1062: Duplicate entry 'testuser' for key 'username'
第10行的第一个INSERT工作并报告errno = 0。 第二次插入失败,错误号为errno = 1-62,并显示一条消息,指示用户名重复。
现在,删除//在第14行,以便将$ dbConn内容打印到输出中,我得到:
H:>php print_r_test2.php
PHP Version: 5.4.10
Created print_r_test table.
Truncated print_r_test table.
INSERT#1: 0:
$dbConn: mysqli Object
(
[affected_rows] => -1
[client_info] => mysqlnd 5.0.10 - 20111026 - $Id: b0b3b15c693b7f6aeb3aa66b646fee339f175e39 $
[client_version] => 50010
[connect_errno] => 0
[connect_error] =>
[errno] => 1062
[error] => Duplicate entry 'testuser' for key 'username'
[error_list] => Array
(
[0] => Array
(
[errno] => 1062
[sqlstate] => 23000
[error] => Duplicate entry 'testuser' for key 'username'
)
)
[field_count] => 0
[host_info] => 127.0.0.1 via TCP/IP
[info] =>
[insert_id] => 0
[server_info] => 5.6.19
[server_version] => 50619
[stat] => Uptime: 26920 Threads: 2 Questions: 97 Slow queries: 0 Opens: 85 Flush tables: 1 Open tables: 61 Queries per second avg: 0.003
[sqlstate] => 00000
[protocol_version] => 10
[thread_id] => 20
[warning_count] => 0
)
INSERT#2: 0:
第二个INSERT报告OK表示0,但显然失败。
这里似乎发生的情况是print_r($dbConn, true)
导致$dbConn
对象的errno
和error
属性设置为零。 这导致我的代码无法找到1062错误。
如果我将print_r
行注释掉并复制INSERT#2
行,那么它将两次打印出1062错误消息。
如果我复制了print_r
行,那么我看到第二个打印出errno -> 0
, error
为空。 我注意到的是,第二个显示连接stat
中的“ Questions
计数增加了一个。 所以我的想法是$dbConn
的print_r
导致对MySQL的附加查询,该查询成功并为OK返回0,并删除那里的先前值。
这似乎不是很有帮助,还是我在这里想念的东西明显地令人眼花obvious乱?
谢谢。
在下面$dbConn
的评论之后,我的问题是我在做错什么(如果有的话),从而打破了errno
并在$dbConn
对象中返回了error
?
与print_r
无关。 将最后一行替换为:
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL . $dbConn->stat . PHP_EOL;
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL . $dbConn->stat . PHP_EOL;
结果输出为:
INSERT#2: 1062: Duplicate entry 'testuser' for key 'username'
Uptime: 29364 Threads: 2 Questions: 136 Slow queries: 0 Opens: 91 Flush tables: 1 Open tables: 61 Queries per second avg: 0.004
INSERT#2: 0:
Uptime: 29364 Threads: 2 Questions: 137 Slow queries: 0 Opens: 91 Flush tables: 1 Open tables: 61 Queries per second avg: 0.004
这样做:
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
结果是:
INSERT#2: 1062: Duplicate entry 'testuser' for key 'username'
INSERT#2: 1062: Duplicate entry 'testuser' for key 'username'
如果读取连接对象不是幂等操作,那对我来说就像是一个陷阱,是问题和挫败感的根源。 因此,我的问题再次是,我做错了什么或缺少什么吗?还是这是mysqli的某些奇怪功能?
如果查看mysqli->stat()
的文档 ,则此函数可在服务器上执行命令“ mysqladmin status”并返回服务器为此返回的内容。 如果查看mysqli->errno
的文档,您会看到它“返回最近函数调用的错误代码”。
那会怎样呢?
您执行查询,并读取错误代码。 然后,执行另一个不会失败的命令,并读取该命令的错误代码。 这正是您应该期望发生的事情。
如果在调用stat()之后需要errno或error的值,则在调用stat()之前,没有什么阻止您将这些值存储在变量中的:
$a = $dbConn->errno;
$b = $dbConn->error;
$c = $dbConn->stat();
echo $a . $b . $c;
这是一个有趣的问题,在浏览了文档后,我找到了答案: http : //php.net/manual/en/class.mysqli.php
这些是对象属性:errno,错误。 因此访问它们不会影响对象的状态。
另一方面,stat()是对对象的方法调用。 这意味着errno和error将被更新以反映该调用是成功还是失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.