Discuss $stmt = $conn->prepare is a non-object in the PHP Development forum on Dev Shed. $stmt = $conn->prepare is a non-object PHP Development forum discussing coding practices, tips on PHP, and other PHP-related topics. PHP is an open source scripting language that has taken the web development industry by storm.
Posts: 158
Time spent in forums: 1 Day 20 h 11 m 16 sec
Reputation Power: 92
PHP5 - $stmt = $conn->prepare is a non-object
Welcome to the next installment of Stupid Mike Mistakes...
PHP Code:
if (array_key_exists('edit', $_GET)) {
echo $blogEdit = $_GET['edit'];
$select = "blog_no, date_posted, heading, post FROM blog WHERE blog_no = ?";
if ($stmt = $conn->prepare($select)) {
echo "Made it into the loop...";
$stmt->bind_param('i', $blogEdit);
if (!$stmt->execute()) {echo $stmt->error;}
$stmt->bind_result($blog['blog_no'], $blog['date_posted'], $blog['heading'], $blog['post']);
$stmt->fetch();
$stmt->close();
}
$blog['date_readable'] = date('l, F j, Y', strtotime($blog['date_posted']));
}
I constantly reuse scripts and this one is no exception. I copy/pasted this from another script and changed the column and table names and this one will not work.
This is a copy/paste from phpMyAdmin showing the table name and columns and unless I'm really, really, stupid today they are correct.
Code:
localhost big0mike_wop blog
# Column Type Collation Attributes Null Default Extra Action
1 blog_no int(9) No None AUTO_INCREMENT Change Drop More
2 date_posted date No None Change Drop More
3 heading varchar(128) utf8_unicode_ci No None Change Drop More
4 post mediumtext utf8_unicode_ci No None Change Drop More
echo $blogEdit displays a valid variable for blog_no but it doesn't get to the "Made it into the loop" line. I removed the IF around $stmt = $conn->prepare and that's when I got the "Call to a member function bind_param() on a non-object" error. I added a var_dump and $stmt is bool(false) but I'm at a loss as to why.
Later in the script I have the default behavior which is to load all the blog posts:
PHP Code:
$select = "SELECT blog_no, date_posted, heading, post FROM blog ORDER BY blog_no DESC";
$result = $conn->query($select);
while ($row = $result->fetch_assoc()) {
$blog[] = array(
'blog_no' => $row['blog_no'],
'date_posted' => $row['date_posted'],
'date_readable' => date('l, F j, Y', strtotime($row['date_posted'])),
'heading' => $row['heading'],
'post' => $row['post']
);
}
And this works so I know $conn is valid as are my table names.
Any ideas or trouble shooting tips? I don't know much on how to trouble shoot, obviously.
"They that can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety." -Benjamin Franklin
"The greatest tragedy of this changing society is that people who never knew what it was like before will simply assume that this is the way things are supposed to be." -2600 Magazine, Fall 2002
Posts: 1,870
Time spent in forums: 1 Month 2 Weeks 2 Days 22 m 32 sec
Reputation Power: 813
The try-catch won't help you, because if there was an exception, you'd already see it (assuming your PHP is correctly configured with all error messages turned on). You need to explicitly tell MySQLi to use exceptions instead of "dying silently":
PHP Code:
// turn on error reporting and throw exception on every error
$mysqli_driver = new mysqli_driver();
$mysqli_driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT;
$db = new mysqli(...);
And I strongly suggest doing that. Those "silent errors" (using the return value to indicate an issue) are terrible -- as you've just experienced. Either you write dozens of lines of the same stupid checks, or the script will keep running until it crashes at the next opportunity with some weird error message (like this "non-object" stuff). Exceptions are much better in that aspect.
Posts: 158
Time spent in forums: 1 Day 20 h 11 m 16 sec
Reputation Power: 92
Quote:
Originally Posted by Jacques1
The try-catch won't help you, because if there was an exception, you'd already see it (assuming your PHP is correctly configured with all error messages turned on). You need to explicitly tell MySQLi to use exceptions instead of "dying silently":
That's actually the first thing I checked because I received no errors. My local PHP is setup with E All and E Strict reporting. But, I assume that since I didn't get any errors that your code above is something in addition to the PHP error reporting?
My question on that would be is this something you want to remove in a production environment? Like on your production server you don't want all that error reporting because it can give hackers clues as to how to break/break into things. Will the MySQLI error reporting do the same?
Posts: 1,870
Time spent in forums: 1 Month 2 Weeks 2 Days 22 m 32 sec
Reputation Power: 813
Quote:
Originally Posted by big0mike
But, I assume that since I didn't get any errors that your code above is something in addition to the PHP error reporting?
Yes. By default, MySQLi doesn't tell you if the connection or a query fails. You have to check that yourself by inspecting the return value of each function (it's false in case of an error). This is exactly what the old MySQL extension did.
The code above changes that. MySQLi will now throw an exception whenever something goes wrong.
Quote:
Originally Posted by big0mike
My question on that would be is this something you want to remove in a production environment? Like on your production server you don't want all that error reporting because it can give hackers clues as to how to break/break into things. Will the MySQLI error reporting do the same?
Exceptions are special errors, so turning off display_errors in the php.ini will silence them like all other errors. So there's no risk of leaking information -- unless you make the common mistake of catching the exception and echoing the message. This will of course show the message no matter what you've set in your configuration.
Posts: 1,870
Time spent in forums: 1 Month 2 Weeks 2 Days 22 m 32 sec
Reputation Power: 813
Quote:
Originally Posted by big0mike
So you are saying that since my real host has the errors off I'll be fine provided I remove
{echo $stmt->error;}
from my code after I know the script is working?
There's no reason to ever have that piece of code in your script. On your development server with all error messages turned on, uncaught exceptions will automatically dump a detailed error report on the screen. On your live server will all error messages turned off, the screen will be blank (which gives you the chance to display an apology on the screen, log the error etc.).
As you can see, exceptions already print the message when they're supposed to, so there's absolutely no reason to do that "by hand" using echo or die() or whatever.
In fact, you should never output internal error messages with echo or die(). The problem is that you circumvent the error system and lose control over your messages. Exceptions and errors can be turned off globally, but an echo is an echo and can't be turned off. This leaves you with going through your whole code each time and removing all those special echos. And if you forget any, they'll show up on your live site -- not really a good solution, right?
So simply don't fumble with error messages. When you've added the two lines, it's all done. No need for try-catch, echo, die() etc. Just let the exceptions do their work.
The only time you'll need to intervene in the standard error process is when you want to do something special with an error. Let's say you have two database servers. In that case it would make sense to try connecting to the second server if the first one failed.
Posts: 158
Time spent in forums: 1 Day 20 h 11 m 16 sec
Reputation Power: 92
Quote:
Originally Posted by Jacques1
So simply don't fumble with error messages. When you've added the two lines, it's all done. No need for try-catch, echo, die() etc. Just let the exceptions do their work.
Sounds like a plan. If I'd known about turning on the errors before it probably could've saved me some hair pulling
Posts: 2,880
Time spent in forums: 1 Year 2 Weeks 2 Days 8 h 3 m 52 sec
Reputation Power: 581
Jacques1 and I do not completely see eye to eye on the usefulness of try/catch for debugging purposes. He likes to use "no reason ever" and I say never say never. There may be some OS dependencies involved but these exceptions, even if you are able to turn on errors, occasionally wind up only in the logs rather than on the web page itself. This can be problematic for those without full admin rights rendering the exception message useless. I personally find it easier and more convenient to use try/catch to determine errors generically, than chasing where error messages might be. I am assured that it will show up on the web page I am trying to debug. The choice is obviously up to you and what works best in your case. Where we do agree is that if you are not handling exceptions for a specific purpose, the try/catch should be removed for production, as should turning off errors.
Posts: 158
Time spent in forums: 1 Day 20 h 11 m 16 sec
Reputation Power: 92
Quote:
Originally Posted by gw1500se
Jacques1 and I do not completely see eye to eye on the usefulness of try/catch for debugging purposes. He likes to use "no reason ever" and I say never say never.
I can see your point and agree to never say never. I'm gonna try turning on the errors and see what kind of feedback it gives me since it's two lines that I never have to worry about changing. If it proves not so useful, with the issues you point out, I'll know to give the try/catch scenario a shot.