3

I have this function and it keeps giving out the error "Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error' in..." The error is directing me to the line "$row = $q2->fetchAll(PDO::FETCH_OBJ);". I've searched tonnes for a solution but to no avail. My code appears to be the same format as the examples given in the php docs...

Here's the function updated as per TML's suggestions:

//gets a record by id and sets object properties to it's values
function getById($sid) {
    global $conf, $pdo;
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //checks to see if a record exists for the given id
    try {
        $stmt  = $pdo->prepare('Use ' . $conf['database'] . '; select mem_id as "_id", mem_name as "_name", mem_info as "_info",
                                mem_password as "_password", mem_email as "_email", mem_image as "_image",
                                mem_group as "_group"
                                from ' . $conf['prefix'] . 'members
                                where mem_id = ?;');
        echo"85 <br />";
        $stmt->execute(array($sid));
        echo"86 <br />";
        $rows = $stmt->fetchAll(PDO::FETCH_OBJ);
        echo"90 <br />";
        print_r($rows);
        if (count($rows) !== 1) {
            throw new Exception("Some exception here");
        }
        foreach($rows[0] as $field=>$value) {
            $this->$field = $value;
            echo"97 <br />";
        }
    } catch (PDOException $e) {
        echo"something went wrong! " . var_dump($e);
    }
}

var_dump output:

object(PDOException)[4]
  protected 'message' => string 'SQLSTATE[HY000]: General error' (length=30)
  private 'string' (Exception) => string '' (length=0)
  protected 'code' => string 'HY000' (length=5)
  protected 'file' => string 'D:\wamp\www\testing\scripts\Kantan\classes\Member.php' (length=53)
  protected 'line' => int 86
  private 'trace' (Exception) => 
    array (size=2)
      0 => 
        array (size=6)
          'file' => string 'D:\wamp\www\testing\scripts\Kantan\classes\Member.php' (length=53)
          'line' => int 86
          'function' => string 'fetchAll' (length=8)
          'class' => string 'PDOStatement' (length=12)
          'type' => string '->' (length=2)
          'args' => 
            array (size=1)
              ...
      1 => 
        array (size=6)
          'file' => string 'D:\wamp\www\testing\scripts\Kantan\test.php' (length=43)
          'line' => int 5
          'function' => string 'getById' (length=7)
          'class' => string 'Member' (length=6)
          'type' => string '->' (length=2)
          'args' => 
            array (size=1)
              ...
  private 'previous' (Exception) => null
  public 'errorInfo' => 
    array (size=1)
      0 => string 'HY000' (length=5)
  public 'xdebug_message' => string '<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> PDOException: SQLSTATE[HY000]: General error in D:\wamp\www\testing\scripts\Kantan\classes\Member.php on line <i>86</i></th></tr>
<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeee'... (length=1472)

Thanks in advance for any help.

Jamal
  • 151
  • 1
  • 2
  • 7

1 Answers1

1

A better way to write the code above - and one that will likely fix your problem - might look something like this:

//gets a record by id and sets object properties to it's values
function getById($sid) {
    global $conf, $pdo;
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //checks to see if a record exists for the given id
    try {
        $stmt  = $pdo->prepare('select mem_id as "_id", mem_name as "_name", mem_info as "_info",
                                mem_password as "_password", mem_email as "_email", mem_image as "_image",
                                mem_group aS "_group"
                                from members
                                where mem_id = ?');
        $stmt->execute(array($sid));

        $rows = $stmt->fetchAll(PDO::FETCH_OBJ);
        if (count($rows) !== 1) {
            throw new Exception("Some exception here");
        }
        foreach($rows[0] as $field=>$value) {
            $this->$field = $value;
        }
    } catch (PDOException $e) {
        /* handle errors in useful way, don't just die() */
    }
}

Some differences to note:

  1. There's doesn't appear to be any sane reason to query the database twice.
  2. Your code above ignores one of the main benefits of using prepared statements with PDO - namely, parameterization of your queries.
  3. "or die()" leaves a terrible user experience - handle errors more gracefully. I used exception handling in my example here, but that's certainly not the only way to do it; I simply defaulted to that because of your setAttribute call.
  4. Although I left your global variables intact here, you should really consider moving away from using 'global', as it is generally considered pretty poor practice. A little bit of Google work should turn up any number of articles discussing why, but the Law of Demeter is a good place to start.
  5. There's no reason for all those 'USE ' calls; the PDO object will already carry that information for you.

The members of Freenode's ##PHP have put together a tutorial for PDO that you might want to check out before progressing too much further.

TML
  • 12,813
  • 3
  • 38
  • 45
  • Thanks a lot for your reply, I can't try it out now as I have to get off to college, but I will definitely try it out when I get home. I didn't want to use global variabels, but this function cant see the variables if I don't, I will try and work around that later though! – Jamal Feb 11 '13 at 10:41
  • I tried it out, and although I now have nicer code, the same error is persisting... – Jamal Feb 11 '13 at 17:39
  • Can you update the question with the state of your code now? Also, if you don't have a body in your 'catch' statement, give it 'var_dump($e);' at a minimum, and include the result. – TML Feb 11 '13 at 18:04
  • Updated the question, I know you said not to use the USE database; query but it doesn't work without it, even though I include the database in the connection string. – Jamal Feb 11 '13 at 18:32
  • Well, it quite obviously doesn't work *WITH* it, either, as this error comes *because* of the attempt to run multiple queries inside the same prepared statement. My suggestion would be to remove the 'USE' statements, and then open a new SO question for the error you're getting when you DON'T use the 'USE database' statement. My guess would be that you have multiple '$pdo' objects floating around in your global namespace, which is exactly why you should drop 'global': function getById($sid, $pdo) { /* don't use 'global' at all here */ ... } – TML Feb 11 '13 at 19:08
  • Oh I see! Thanks, given that information I will play around with it and see if I can work something out. You've been a big help, cheers. – Jamal Feb 11 '13 at 19:45