#1
  1. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Location
    Glendale AZ
    Posts
    184
    Rep Power
    93

    $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.

    Thanks,

    Mike
  2. #2
  3. Sarcky
    Devshed Supreme Being (6500+ posts)

    Join Date
    Oct 2006
    Location
    Pennsylvania, USA
    Posts
    10,908
    Rep Power
    6351
    PHP Code:
        $select "blog_no, date_posted, heading, post FROM blog WHERE blog_no = ?"
    Now...that line has the word "select" in it, but where is that word?
    HEY! YOU! Read the New User Guide and Forum Rules

    "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

    Think we're being rude? Maybe you asked a bad question or you're a Help Vampire. Trying to argue intelligently? Please read this.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Jul 2003
    Posts
    3,465
    Rep Power
    594
    Use a try/catch around the prepare statement. If you echo 'getMessage' in the catch block it should tell you why the prepare is failing.
    There are 10 kinds of people in the world. Those that understand binary and those that don't.
  6. #4
  7. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Location
    Glendale AZ
    Posts
    184
    Rep Power
    93
    Originally Posted by ManiacDan
    PHP Code:
        $select "blog_no, date_posted, heading, post FROM blog WHERE blog_no = ?"
    Now...that line has the word "select" in it, but where is that word?
    Wow, I lower the bar with every post I make... Thanks!

    Originally Posted by gw1500se
    Use a try/catch around the prepare statement. If you echo 'getMessage' in the catch block it should tell you why the prepare is failing.
    I seem to remember hearing about that one. I'll check that out since it will likely be useful in the future.

    Comments on this post

    • ManiacDan agrees : Happens to all of us
  8. #5
  9. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    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.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  10. #6
  11. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Location
    Glendale AZ
    Posts
    184
    Rep Power
    93
    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?

    Mike
  12. #7
  13. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    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.



    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.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  14. #8
  15. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Location
    Glendale AZ
    Posts
    184
    Rep Power
    93
    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?

    So, in my connection script I'll just add those two lines right before my connection line?

    PHP Code:
    $mysqli_driver = new mysqli_driver();
    $mysqli_driver->report_mode MYSQLI_REPORT_ERROR MYSQLI_REPORT_STRICT;

    $conn = new mysqli("localhost"$user$pwd"big0mike_wop") or die ("Cannot open database"); 
  16. #9
  17. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    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.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  18. #10
  19. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Location
    Glendale AZ
    Posts
    184
    Rep Power
    93
    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

    Thanks!

    Mike
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Jul 2003
    Posts
    3,465
    Rep Power
    594
    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.
    There are 10 kinds of people in the world. Those that understand binary and those that don't.
  22. #12
  23. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Location
    Glendale AZ
    Posts
    184
    Rep Power
    93
    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.

    Thanks!

    Mike

IMN logo majestic logo threadwatch logo seochat tools logo