php PDO - 致命错误:在非对象上调用成员函数 fetch()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19017682/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PDO - Fatal error: Call to a member function fetch() on a non-object
提问by user2693017
if I try to run the following PHP code, I get a
如果我尝试运行以下 PHP 代码,我会得到一个
Call to a member function fetch() on a non-object.
在非对象上调用成员函数 fetch()。
Do you know why? I use the same code on another site, where it works just fine.
你知道为什么吗?我在另一个网站上使用了相同的代码,在那里它工作得很好。
<?php
$username = ($_GET ['user']);
try {
$dbh = new PDO("mysql:host=localhost;dbname=***", '***', '***');
} catch (PDOException $e) {
echo $e->getMessage();
}
$sth = $dbh->query( "SELECT user, captcha
FROM xf_captcha WHERE user='$username'" );
print_r($sth->fetch());
?>
Edit:
编辑:
$sth = $dbh->query( "SELECT username, user_state, last_activity, alerts_unread, conversations_unread, message_count
FROM xf_user WHERE username='$user'" );
$row = $sth->fetch();
Edit2:
编辑2:
Does this look safe, should I do more ?
这看起来安全吗,我应该做更多吗?
<?php
$username = ($_GET ['user']);
try {
$dbh = new PDO("mysql:host=localhost;dbname=***", '***', '***');
} catch (PDOException $e) {
echo $e->getMessage();
}
$sth = $dbh->prepare("SELECT username, captcha, timestamp
FROM xf_captcha
WHERE username = :username", array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $username));
print_r($sth->fetch());
?>
采纳答案by Fluffeh
Your code has the variable $username
in the top part of your question, but you then have $user
in the bottom section.
您的代码$username
在问题的顶部有变量,但$user
在底部有变量。
Are you perhaps meaning to use the same variable?
您可能打算使用相同的变量吗?
$username = ($_GET ['user']);
$sth = $dbh->query( "SELECT username, user_state, last_activity, alerts_unread, conversations_unread, message_count
FROM xf_user WHERE username='$user'" );
// ^^ Should this ALSO be $username ?
$row = $sth->fetch();
Edit: Okay, now you are just being cute with your PDO::ATTR_EMULATE_PREPARES
. Observe this:
编辑:好的,现在你只是对你的PDO::ATTR_EMULATE_PREPARES
. 观察这一点:
Database and table structure:
数据库和表结构:
Database changed
mysql> show tables
-> ;
+----------------+
| Tables_in_prep |
+----------------+
| users |
+----------------+
1 row in set (0.00 sec)
mysql> select * from users;
+----+---------+--------+
| id | userid | pass |
+----+---------+--------+
| 1 | Fluffeh | mypass |
+----+---------+--------+
1 row in set (0.00 sec)
And some PHP code that is copied from yours, with the added PDO attribute:
还有一些从您那里复制的 PHP 代码,并添加了 PDO 属性:
<?php
//$username = ($_GET ['user']);
$username="Fluffeh";
$dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
echo "Trying to use $username.\n";
print_r($sth->fetch());
echo "----------------------------------------\n\n";
?>
<?php
//$username = ($_GET ['user']);
$username="user2693017";
$dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
echo "Trying to use $username.\n";
print_r($sth->fetch());
echo "----------------------------------------\n\n";
?>
<?php
//$username = ($_GET ['user']);
$username="Oh my' or 1=1 or 'm=m";
$dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
echo "Trying to use $username.\n";
print_r($sth->fetch());
echo "----------------------------------------\n\n";
?>
<?php
//$username = ($_GET ['user']);
$username="(select id from users limit 1)";
$dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$sth = $dbh->query( "SELECT userid, pass FROM users WHERE id='$username'" );
echo "Trying to use $username.\n";
print_r($sth->fetch());
echo "----------------------------------------\n\n";
?>
<?php
//$username = ($_GET ['user']);
// Changed this one to be a non-string, you might be checking an ID instead.
$username="(select id from users limit 1)";
$dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$sth = $dbh->query( "SELECT userid, pass FROM users WHERE id=$username" );
echo "Trying to use $username.\n";
print_r($sth->fetch());
echo "----------------------------------------\n\n";
?>
<?php
//$username = ($_GET ['user']);
$username="bob'; drop table users; \
";
// This one is tricker to do in PHP code. I could easily enter this into a text field however.
$dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
//$sth = $dbh->query( "SELECT userid, pass FROM users WHERE id='$username'" );
echo "Trying to use $username.\n";
print_r($sth->fetch());
echo "----------------------------------------\n\n";
?>
And the output:
和输出:
Trying to use Fluffeh.
stdClass Object
(
[userid] => Fluffeh
[pass] => mypass
)
----------------------------------------
Trying to use user2693017.
----------------------------------------
Trying to use Oh my' or 1=1 or 'm=m.
stdClass Object
(
[userid] => Fluffeh
[pass] => mypass
)
----------------------------------------
Trying to use (select id from users limit 1).
----------------------------------------
Trying to use (select id from users limit 1).
stdClass Object
(
[userid] => Fluffeh
[pass] => mypass
)
----------------------------------------
Trying to use bob'; drop table users; \
.
----------------------------------------
Oh, the reason I left the last one till LAST is this output now in my database:
哦,我把最后一个留到最后一个的原因是现在我的数据库中的这个输出:
mysql> show tables;
Empty set (0.00 sec)
Yes, that's right, I just dropped a table. Let me say that again, I had a select statement, and with a little trickery I entered in a value that ANYONE with half a brain and some malicious intent could do into a text field, and DROPPED YOUR TABLE.
是的,没错,我刚丢了一张桌子。让我再说一遍,我有一个 select 语句,我用一点技巧输入了一个值,任何有半脑和恶意的人都可以在文本字段中输入该值,然后删除您的表格。
Now, granted, if you are setting things up properly, you might well set up a different user for the select statements, and only grant them select
rights from your database, to stop this sort of thing happening - but lets be honest... you aren't are you?
现在,当然,如果您设置正确,您很可能会为 select 语句设置一个不同的用户,并且只select
从您的数据库授予他们权限,以阻止此类事情的发生 - 但老实说......不是吗?
Clearly setting that emulation is not enough. Seriously, now PLEASE do go read that answer, use prepared statements and use params if you want to be secure in your code.
显然设置该仿真是不够的。说真的,现在请务必阅读该答案,如果您想确保代码安全,请使用准备好的语句并使用参数。
回答by Orion
Where is your Execute statement being called? Is this also inside your ->query
? If not think of using the following for also a better query build up.:
你的 Execute 语句在哪里被调用?这也在你的里面->query
吗?如果不考虑使用以下内容来构建更好的查询。:
<?php
$username = ($_GET['user']);
try {
$dbh = new PDO("mysql:host=localhost;dbname=***", '***', '***');
} catch (PDOException $e) {
echo $e->getMessage();
}
$statement = "SELECT user, captcha FROM xf_captcha WHERE user=:username";
//If you have query as a method(Which I don't think so but if you can change "prepare" to your "query"
$sth = $dbh->prepare($statement);
$sth->execute(array(":username" => $username));
$row = $sth->fetch(PDO::FETCH_ASSOC);
?>
In the execute parentheses you can use an array to fill the parameter :username
for the variable $username
在执行括号中,您可以使用数组来填充:username
变量的参数$username
I think looking into PDO Class examples might also be good for a better understanding of PDO and methods(You can also refer to the PHP PDO Manual)
我认为查看 PDO 类示例也可能有助于更好地理解 PDO 和方法(您也可以参考 PHP PDO 手册)
回答by a coder
It happens when the table doesn't exist also. make sure it actually exists, and isn't just a holder in the database due to hard drive errors.
当表不存在时也会发生这种情况。确保它确实存在,并且不只是由于硬盘驱动器错误而在数据库中的一个持有者。
When that happens I suggest you recreate the database/table if phpMyAdmin gets an error when trying to read it "manually".
发生这种情况时,如果 phpMyAdmin 在尝试“手动”读取时出错,我建议您重新创建数据库/表。