我完全被mySQLi弄糊涂了。尽管多年来我一直在使用过程性mysql调用,但我希望习惯于为其提供的db security / mySQL注入保护编写准备好的语句。我正在尝试编写一个简单的select语句(是的,我知道为此进行程序调用可提高性能)。运行时,我会得到所有回声,直到击中$result = $stmt->get_result();组件为止。在我看来,这一切都相当简单,但是在阅读了数小时的mySQLi手册后,我感到茫然。任何想法为什么会失败?
$result = $stmt->get_result();
*注:这是一个测试环境,虽然没有进行字符的清理/转义,但我只是将有效内容传递给变量$ username和$ email。而且,我从头到尾都在寻找解决问题的方法。
function checkUsernameEmailAvailability($username, $email) { //Instantiate mysqli connection @$mysqli = new mysqli(C_HOST,C_USER,C_PASS,C_BASE) or die("Failed to connect to MySQL database..."); if (!$mysqli) { echo 'Error: Could not connect to database. Please try again later...'; exit; } else { echo 'mysqli created'; } /* Create a prepared statement */ if($stmt = $mysqli -> prepare("SELECT username,email FROM tb_users WHERE username=? OR email=?")) { echo '<br />MYSQLi: '; /* Bind parameters s - string, b - boolean, i - int, etc */ $stmt -> bind_param("ss", $username, $email); echo '<br />paramsBound...'; /* Execute it */ $stmt -> execute(); echo '<br />Executed'; $result = $stmt->get_result(); echo '<br />Result acquired'; /* now you can fetch the results into an array - NICE */ $myrow = $result->fetch_assoc(); echo '<br />Fetched'; /* Close statement */ /$stmt -> close(); echo '<br />Done mysqli'; } }
另外,每次调用函数时都必须实例化mysqli吗?我假设它们不是像过程mysql中那样的持久数据库连接。是的,我知道这是一个范围问题,并且不,我无法理解此类变量的作用域。当我在函数外部声明它时,进入函数时它不可用。
__如果我将第12行从以下位置更改,则进行 更新 :
if($stmt = $mysqli -> prepare("SELECT username,email FROM tb_users WHERE username=? OR email=?")) {
至:
$stmt = $mysqli->stmt_init(); if($stmt = $mysqli -> prepare("SELECT username,email FROM tb_users WHERE username=? OR email=?")) { if(!stmt) echo 'Statement prepared'; else echo 'Statement NOT prepared';
我没有准备好声明。现在我更加困惑了。
更新: 我联系了我的托管服务提供商,显然支持mySQLi,并且存在mysqlnd驱动程序。也许有一种方法可以简单地对此进行测试?尽管他们通常在过去给了我很多知识渊博的答案。
更新…再次: 我自己检查了服务器功能,发现,虽然存在mysqli和PDO,但没有mysqlnd。因此,我理解了为什么get_result()无法工作(我认为需要mysqlnd),我仍然不明白为什么预处理语句本身将无法工作。
通过一些检查,即使我的主机上安装了mysqli,显然mysqlnd驱动程序也不存在。因此,不能使用get_result()(PHP手册将get_result定义为mysqlnd依赖),取而代之的是,需要做一些额外的编码以按我希望的方式处理我的结果。
因此,我决定尝试并了解PDO的工作原理,几分钟之内,瞧!
将上面的代码替换为:
function checkUsernameEmailAvailability($username, $email) { echo 'pdo about to be created'; $dsn = 'mysql:dbname='.C_BASE.';host='.C_HOST; $user = C_USER; $password = C_PASS; try { $dbh = new PDO($dsn, $user, $password); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); } $params = array(':username' => $username, ':email' => $email); try{ $sth = $dbh->prepare('SELECT username,email FROM tb_users WHERE username = :username OR email = :email '); } catch(PDOException $e) { echo 'Prepare failed: ' . $e->getMessage(); } try{ $sth->execute($params); } catch(PDOException $e) { echo 'Execute failed: ' . $e->getMessage(); } $result = $sth->fetch(PDO::FETCH_ASSOC); print_r($result); }
我可以想到的错误检查量不多,而且一开始就完全没有问题!
最终密码
function checkUsernameEmailAvailability($username, $email) { $dsn = 'mysql:dbname='.C_BASE.';host='.C_HOST; $user = C_USER; $password = C_PASS; new PDO($dsn, $user, $password); $params = array(':username' => $username, ':email' => $email); $sth = $dbh->prepare('SELECT username,email FROM tb_users WHERE username = :username OR email = :email '); $sth->execute($params); $result = $sth->fetch(PDO::FETCH_ASSOC); print_r($result); }