#1
  1. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2009
    Posts
    677
    Rep Power
    7

    Why a non-object?


    I receive the error on the $statement2->bind_param line. $statement1 runs just fine, and they appear to be identical. Any idea why $statement2 is a non-object?
    Code:
    Fatal error: Call to a member function bind_param() on a non-object ..... line 15.
    
    $statement2->bind_param('i', $col0);
    PHP Code:
    function buildListing() {
      global 
    $link;
      
    $statement1 $link->prepare("SELECT e.`ID`, e.`Begin`, c.`Customer Name`, e.`JobNumber`, u.`EmpName`, e.`End`, e.`MileageRate`, e.`PerDiemRate` FROM expensereportsrebuilt AS e INNER JOIN customers AS c ON e.`CID` = c.`ID` INNER JOIN userpass AS u ON e.`TechID` = u.`ID`");
      
    $statement1->execute();
      
    $statement1->bind_result($col0,$col1,$col2,$col3,$col4,$col5,$col6,$col7);
      while (
    $statement1->fetch()) {
        
    $start DateTime::createFromFormat('Y-m-d'$col1);
        
    $end DateTime::createFromFormat('Y-m-d'$col5);
        
    $pDays $start->diff($end);
        
    $pCost $pDays->format('%R%a') * $col7;
        
    $totals array_fill(010'');
        
    $statement2 $link->prepare("SELECT `CatID`, SUM(`Cost`) FROM expenseitemsrebuilt WHERE `ERID` = ? GROUP BY `CatID`");
        
    $statement2->bind_param('i'$col0);
        
    $statement2->execute();
        
    $statement2->bind_result($colA,$colB);
        while (
    $statement2->fetch()) {
          
    $totals[$colA] = $colB;
        }
        
    $statement2->close();
        
    $mCost $totals[6] * $col6;
        echo 
    '<TR class="highlightable" href="?loc=exre&action=view&id=' $col0 '"><TD>' $col0 '</TD><TD>' $col1 '</TD><TD>' $col2 '</TD><TD>' $col3 '</TD><TD>' $col4 '</TD><TD>' $totals[0] . '</TD><TD>' $totals[1] . '</TD><TD>' $totals[2] . '</TD><TD>' $totals[3] . '</TD><TD>' $totals[4] . '</TD><TD>' $mCost '</TD><TD>' $pDays '</TD><TD>' $pCost '</TD><TD>' $totals[5] . '</TD><TD>' $totals[6] . '</TD><TD>' $totals[7] . '</TD><TD>' $totals[8] . '</TD><TD>' $totals[9] . "</TD></TR>\n";
      }
      
    $statement1->close();

    On any kind of dump I would get a NULL, bool(false) which is why I figure the non-object, but why this is... :-/ Other than the query string itself, it looks no different than the first one which is working just fine...
    Last edited by Triple_Nothing; September 30th, 2013 at 08:09 PM.
    He who knows not and knows not he knows not: he is a fool - shun him. He who knows not and knows he knows not: he is simple - teach him. He who knows and knows not he knows: he is asleep - wake him. He who knows and knows he knows: he is wise - follow him
  2. #2
  3. Wiser? Not exactly.
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2001
    Location
    Bonita Springs, FL
    Posts
    5,953
    Rep Power
    4033
    Add some error reporting to your code so you can see why the prepare call fails. At a guess I'd say you are getting a 'commands out of sync' error. In which case, see: Commands out of sync; you can't run this command now
    Recycle your old CD's, don't just trash them



    If I helped you out, show some love with some reputation, or tip with Bitcoins to 1N645HfYf63UbcvxajLKiSKpYHAq2Zxud
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2009
    Posts
    677
    Rep Power
    7
    Any errors I've been able to fetch have always been "due to non-object" type errors. As to why it fails, I've no clue. The values handed to it are true, and if I run the query myself, all goes fine...
    He who knows not and knows not he knows not: he is a fool - shun him. He who knows not and knows he knows not: he is simple - teach him. He who knows and knows not he knows: he is asleep - wake him. He who knows and knows he knows: he is wise - follow him
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2009
    Posts
    677
    Rep Power
    7
    Can there be any issue with me running $statement2 inside $statement1's while() loop the way I am?

    EDIT: Even this will fail to NULL/false an be a non-object...
    Code:
    $statement2 = $link->prepare("SELECT * FROM expenseitemsrebuilt");
    Last edited by Triple_Nothing; September 30th, 2013 at 08:32 PM.
    He who knows not and knows not he knows not: he is a fool - shun him. He who knows not and knows he knows not: he is simple - teach him. He who knows and knows not he knows: he is asleep - wake him. He who knows and knows he knows: he is wise - follow him
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2009
    Posts
    677
    Rep Power
    7
    ANSWER: In order to run a Prepared statement within another, the first must store its results before the second one can start.

    PHP Code:
    function buildListing() { 
      global 
    $link
      
    $statement1 $link->prepare("SELECT e.`ID`, e.`Begin`, c.`Customer Name`, e.`JobNumber`, u.`EmpName`, e.`End`, e.`MileageRate`, e.`PerDiemRate` FROM expensereportsrebuilt AS e INNER JOIN customers AS c ON e.`CID` = c.`ID` INNER JOIN userpass AS u ON e.`TechID` = u.`ID`");
       
    $statement1->execute(); 
      
    $statement1->bind_result($col0,$col1,$col2,$col3,$col4,$col5,$col6,$col7);
      
    $query->store_result(); 
      while (
    $statement1->fetch()) { 
        
    $start DateTime::createFromFormat('Y-m-d'$col1); 
        
    $end DateTime::createFromFormat('Y-m-d'$col5); 
        
    $pDays $start->diff($end); 
        
    $pCost $pDays->format('%R%a') * $col7
        
    $totals array_fill(010''); 
        
    $statement2 $link->prepare("SELECT `CatID`, SUM(`Cost`) FROM expenseitemsrebuilt WHERE `ERID` = ? GROUP BY `CatID`");
        
    $statement2->bind_param('i'$col0); 
        
    $statement2->execute(); 
        
    $statement2->bind_result($colA,$colB); 
        while (
    $statement2->fetch()) { 
          
    $totals[$colA] = $colB
        } 
        
    $statement2->close(); 
        
    $mCost $totals[6] * $col6
        echo 
    '<TR class="highlightable" href="?loc=exre&action=view&id=' $col0 '"><TD>' $col0 '</TD><TD>' $col1 '</TD><TD>' $col2 '</TD><TD>' $col3 '</TD><TD>' $col4 '</TD><TD>' $totals[0] . '</TD><TD>' $totals[1] . '</TD><TD>' $totals[2] . '</TD><TD>' $totals[3] . '</TD><TD>' $totals[4] . '</TD><TD>' $mCost '</TD><TD>' $pDays '</TD><TD>' $pCost '</TD><TD>' $totals[5] . '</TD><TD>' $totals[6] . '</TD><TD>' $totals[7] . '</TD><TD>' $totals[8] . '</TD><TD>' $totals[9] . "</TD></TR>\n";
       } 
      
    $statement1->close(); 

    Last edited by Triple_Nothing; October 1st, 2013 at 03:11 PM.
    He who knows not and knows not he knows not: he is a fool - shun him. He who knows not and knows he knows not: he is simple - teach him. He who knows and knows not he knows: he is asleep - wake him. He who knows and knows he knows: he is wise - follow him
  10. #6
  11. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Hi,

    several things:

    • Turn on error reporting for MySQLi (see below). Then you'll get proper exceptions instead of this "non-object" stuff caused by MySQLi abusing the return values to signal errors.
    • Use a join, not a nested loop. Doing queries in a loop is extremely inefficient, because you quickly end up bombarding the database system with dozens or even hundreds of queries per request.
    • You should format your code. Use multiple lines for your queries instead of stuffing them into a single line. Separate logical code sections with empty lines etc.
    • Use sensible variable names. If all your variables are named $col167 and $statement5149, that makes it extremely difficult to read the code.
    • Use standard names in your database (no whitespace, no reserved words). Then get rid of the stupid backticks.



    Error reporting for MySQLi: (put this before the connection code)

    PHP Code:
    <?php

    $mysqli_driver 
    = new mysqli_driver();
    $mysqli_driver->report_mode MYSQLI_REPORT_ERROR MYSQLI_REPORT_STRICT;
    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".
  12. #7
  13. Mad Scientist
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Oct 2007
    Location
    North Yorkshire, UK
    Posts
    3,661
    Rep Power
    4124
    Firstly, in the preparation fails (eg malformed SQL) then $statement2 will not be an onject but nul or false (already hinted too). PDO in exception mode would probably throw an exeception and could be wrapped in a try/catch block...but this is MySQLi..so there!

    Also:

    Given that the SQL in statement2 does not depend on the values in the current iteration, you can move this outside your while loop. This will mean that the preparation only has to be done once (one of the big advantages of prepared statements), the bind and execute is all that needs to happen in the loop.

    However, that is moot if you can use join and get everything in one go
    I said I didn't like ORM!!! <?php $this->model->update($this->request->resources[0])->set($this->request->getData())->getData('count'); ?>

    PDO vs mysql_* functions: Find a Migration Guide Here

    [ Xeneco - T'interweb Development ] - [ Are you a Help Vampire? ] - [ Read The manual! ] - [ W3 methods - GET, POST, etc ] - [ Web Design Hell ]

IMN logo majestic logo threadwatch logo seochat tools logo