简体   繁体   English

PHP print_r清除mysqli连接对象的状态?

[英]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连接对象中的errnoerror值。 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对象的errnoerror属性设置为零。 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 -> 0error为空。 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. 所以我的想法是$dbConnprint_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM