[英]PHP print_r clears status from a mysqli connection object?
I have a MySQL table where I require three columns to each be unique across the table, userName, userEmail and userUID. 我有一个MySQL表,其中需要三列,每个列在表中是唯一的,分别是userName,userEmail和userUID。 The table is set up with UNIQUE for each of these columns.
对于这些列中的每列,都使用UNIQUE设置了该表。 In order to prevent race conditions I try a single insert of a new user and then pick up the 'duplicate entry' error, parse the error message to determine which column gave problems and then ask the user for new info.
为了防止出现竞争情况,我尝试插入一个新用户,然后选择“重复输入”错误,分析错误消息以确定哪一列出了问题,然后向用户询问新信息。 I was trying to debug this code and placed
print_r($dbConn, true)
to capture the outcome of the INSERT statemment before doing any of the tests for the duplicate column name. 我正在尝试调试此代码,并在对重复的列名称进行任何测试之前,放置了
print_r($dbConn, true)
以捕获INSERT语句的结果。 This broke things big time as it seemed to wipe out the errno
and error
values in the mysqli connection object. 这使事情变得很
errno
,因为它似乎消除了mysqli连接对象中的errno
和error
值。 Here's a cut down sample that illustrates the problem: 以下是说明问题的样本:
<?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;
?>
Note that line 14 is commented out. 请注意,第14行已被注释掉。
If you run this as is (after changing userX, passwordX and databaseX) it works as expected: 如果按原样运行(更改了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'
The first INSERT at line 10 works and reports errno=0. 第10行的第一个INSERT工作并报告errno = 0。 The second insert fails with errno=1-62 and a message indicating the duplicate username.
第二次插入失败,错误号为errno = 1-62,并显示一条消息,指示用户名重复。
Now, removing the //'s on line 14 so that the $dbConn contents are printed to the output and I get: 现在,删除//在第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:
The second INSERT reports 0 for OK but it clearly failed. 第二个INSERT报告OK表示0,但显然失败。
What seems to happen here is that the print_r($dbConn, true)
results in the errno
and error
properties of the $dbConn
conenction object being set to zero. 这里似乎发生的情况是
print_r($dbConn, true)
导致$dbConn
对象的errno
和error
属性设置为零。 That results in my code that looks for the 1062 error failing to find it. 这导致我的代码无法找到1062错误。
If I leave the print_r
line commented out and duplicate the INSERT#2
line then it prints out the 1062 error message twice. 如果我将
print_r
行注释掉并复制INSERT#2
行,那么它将两次打印出1062错误消息。
If I duplicate the print_r
line then I see the second one print out errno -> 0
and error
is empty. 如果我复制了
print_r
行,那么我看到第二个打印出errno -> 0
, error
为空。 What I have noticed is that the second one shows the Questions
count in the connection stat
has been increased by one. 我注意到的是,第二个显示连接
stat
中的“ Questions
计数增加了一个。 So my thinking is that the print_r
of the $dbConn
results in an additional query to MySQL which succeeds and returns 0 for OK and blows away the previous values in there. 所以我的想法是
$dbConn
的print_r
导致对MySQL的附加查询,该查询成功并为OK返回0,并删除那里的先前值。
This doesn't seem to be very helpful or is there something blindingly obvious that I'm missing here? 这似乎不是很有帮助,还是我在这里想念的东西明显地令人眼花obvious乱?
Thanks. 谢谢。
Following @Phil's comment below, my question is what am I doing wrong (if anything) that breaks the errno
and error
returns in the $dbConn
object? 在下面
$dbConn
的评论之后,我的问题是我在做错什么(如果有的话),从而打破了errno
并在$dbConn
对象中返回了error
?
It's nothing to do with print_r
. 与
print_r
无关。 Replacing the last line with: 将最后一行替换为:
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;
results in the output being: 结果输出为:
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
Doing this: 这样做:
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
echo '' . 'INSERT#2: ' . $dbConn->errno . ': ' . $dbConn->error . PHP_EOL;
results in: 结果是:
INSERT#2: 1062: Duplicate entry 'testuser' for key 'username'
INSERT#2: 1062: Duplicate entry 'testuser' for key 'username'
If reading the connection object isn't an idempotent operation then that looks like a bear trap to me and the source of problems and frustration. 如果读取连接对象不是幂等操作,那对我来说就像是一个陷阱,是问题和挫败感的根源。 So my question is, again, is there something that I'm doing wrong or missing or is this some strange feature of mysqli?
因此,我的问题再次是,我做错了什么或缺少什么吗?还是这是mysqli的某些奇怪功能?
If you look at the documentation for mysqli->stat()
, it is a function that executes a command 'mysqladmin status' on the server and returns whatever the server returns for that. 如果查看
mysqli->stat()
的文档 ,则此函数可在服务器上执行命令“ mysqladmin status”并返回服务器为此返回的内容。 If you look at the documentation for mysqli->errno
you'll see that it "returns the error code for the most recent function call". 如果查看
mysqli->errno
的文档,您会看到它“返回最近函数调用的错误代码”。
So what happens? 那会怎样呢?
You execute your query, and you read the error code. 您执行查询,并读取错误代码。 Then you execute an other command that does not fail and you read the error code for that command.
然后,执行另一个不会失败的命令,并读取该命令的错误代码。 This is exactly what you should expect to happen.
这正是您应该期望发生的事情。
If you need to value of errno or error after you call stat(), nothing prevents you from storing these values in a variable before you call stat(): 如果在调用stat()之后需要errno或error的值,则在调用stat()之前,没有什么阻止您将这些值存储在变量中的:
$a = $dbConn->errno;
$b = $dbConn->error;
$c = $dbConn->stat();
echo $a . $b . $c;
It's an interesting question and I found out the answer after looking through the documentation: http://php.net/manual/en/class.mysqli.php 这是一个有趣的问题,在浏览了文档后,我找到了答案: http : //php.net/manual/en/class.mysqli.php
These are object properties: errno, error. 这些是对象属性:errno,错误。 Hence accessing them does not affect the state of the object.
因此访问它们不会影响对象的状态。
On the other hand, stat() is a method call on the object. 另一方面,stat()是对对象的方法调用。 This means that errno and error will be updated to reflect whether that call succeeded or failed.
这意味着errno和error将被更新以反映该调用是成功还是失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.