Jump to content

Call to a member function on a non-object


raydona

Recommended Posts

Hi,
  I have the following class:

   

class User
    {  private $_db;
       
       public function __construct($user = null)
       {
          $this->_db = DB::getInstance();
           .......
       }
       public function find($user = null)
       { if($user)
         { $field = (is_numeric($user)) ? 'id' : 'username';
         $data = $this->_db->get('users', array($field, '=', $user));
           if($data->count())
           { .........
             return true;
           }
         }
         return false;
       }

In class DB I have:
   

public static function getInstance()
      { if(!(self::$_instance)): self::$_instance = new self();
        endif;
        return self::$_instance;
      }

public function get() in class DB, after processing, returns $this, the single instance of class DB, this is assigned to $data which is then used to invoke public function count(), a member function of class DB. I am getting the following error:

 Fatal error: Call to a member function count() on a non-object.

 I would be very grateful if someone can point out my mistake.

Link to comment
Share on other sites

"public function get() in class DB, after processing, returns $this, the single instance of class DB, this is assigned to $data which is then used to invoke public function count()"

 

I think not so much. In User->__construct(), the database class instantiation is given to $this->_db. The database method get() is called and the return from that method is assigned to $data. What is $data?

 

In DB->get(), what is being returned? A complete recordset, probably, but what is the type of the return? An object? An array? It is not the database class instantiated object itself!

 

If PHP is complaining that $data is not an object, and it has the recordset of the query response, then it must be an indexed array of associative arrays (the individual records of the recordset).

 

So, perhaps:

if(is_array($data) && count($data) > 0)

 

What I like to do is:

if( ($data = $this->_db->get('users', array($field, '=', $user)) !== false)

making sure that DB->get() will return false when there is an empty recordset (or an error).

Edited by bsmither
Link to comment
Share on other sites

Hi,
 Many thanks for the replies. I still cannot resolve the problem. I have now included all of the relevant code. The code relating to PDO I got off the internet with which I am not fully conversant.
In class User:
 

public function find($user = null)
{ if($user) //if username is passed, not null
{ $field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count())
{ $this->_data = $data->first();
return true;
}
}
return false;
}

In class DB:
 

class DB
{
private static $_instance = null;
private $_pdo,
$_query,
$_error = false,
$_results,
$_count = 0;

private function __construct()
{ try
{ $dsn = sprintf( "mysql:host='';dbname='';",
Config::get('mysql/host'),
Config::get('mysql/database')
);
$this->_pdo = new PDO( $dsn, Config::get('mysql/username'), Config::get('mysql/password'));
}
catch(PDOException $excp)
{ die($excp->getMessage());
}
}

public static function getInstance()
{ if(!(self::$_instance)): self::$_instance = new self();
endif;
return self::$_instance;
}

public function get($table, $where)
{ return $this->action('SELECT*', $table, $where);
}

public function action($action, $table, $where = array())
{ if(count($where) === 3) //field, operator, value
{ $operators = array('=', '>', '<', '>=', '<=');

$field = $where[0];
$operator = $where[1];
$value = $where[2];

if(in_array($operator, $operators))
{ $sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?";
if(!$this->query($sql, array($value))->error())
{ return $this; //if not an error return $this
}
}
}
return false; //outside of everything return false
}

public function query($sql, $darams = array())
{
$this->_error = false;
if($this->_query = $this->_pdo->prepare($sql))
{ $x = 1;
if(count($darams))
{ foreach($darams as $param)
{ $this->_query->bindValue($x, $param);
$x++;
}
}
if($this->_query->execute())
{ $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
}
else //an error has occured in SQL query
{ $this->_error = true;
}
Link to comment
Share on other sites

your code is testing for error conditions and returning false values, rather than expected data. your code needs to test the returned value, at every step that can fail, and take an appropriate action when there is an error, such as not running the remainder of the database dependent code on the page and to output a message to the visitor. it's actually easier to use exceptions for things like database errors, since you can have several points in the code where an error occurs, but the action you take is the same for all of them.

 

for a database dependent design, any database errors would mean that the page isn't going to function correctly. you should output a user message - 'Sorry, an error is preventing this page from being displayed at this time.' and log (for a live site) or display (during development) all the information you have available about the error - who caused the error (visitor info - ip, loggedin user_id), what occurred - what type of database operation caused the error (connection, query), what the query was, what error was returned from the database, when it occurred (date/time), and where in the application the error occurred (use debug_backtrace).

 

you can handle the switch of where your application detected errors go to by using trigger_error(), which makes use of the php error_reporting/display_errors/log_errors settings, which also control the logging/display of php detected errors.

 

once you have code to handle the errors and to tell you what is going on, you will likely be getting a mysql syntax error that you should be able to solve based on the error message.

Link to comment
Share on other sites

Hello,
  I have following function find() in class User:

public function find($user = null)
   { if($user)
     { $field = (is_numeric($user)) ? 'id' : 'username';
       $data = $this->_db->get('users', array($field, '=', $user));
       if($data->count())
       { $this->_data = $data->first();
         return true;
       }
     }
     return false;
  }

 When line "if($data->count())" is encountered I get following message:
Fatal Error: Call to a member function count() on a non-object
 $data should hold a DB object but doesn't.
   

class User
    {
       private $_db;
       private $_data;
       private $_sessionName;
       private $_isLoggedIn;

       public function __construct($user = null)
       {
          $this->_db = DB::getInstance();
            ..................

 Class DB is shown below:

class DB
{
       private static $_instance = null;
       private $_pdo,                    //PDO object
               $_query,                  //last query executed
               $_error = false,
               $_results,        //store results set of a query
               $_count = 0;

      private function __construct()
      { try
        { $dsn = sprintf( "mysql:host='';dbname='';",
                          Config::get('mysql/host'),
                          Config::get('mysql/database')
                       );
          $this->_pdo = new PDO( $dsn, Config::get('mysql/username'), Config::get('mysql/password'));
        }
        catch(PDOException $excp)
        { die($excp->getMessage());
        }
      }

      public static function getInstance()
      { if(!(self::$_instance)): self::$_instance = new self();
        endif;
        return self::$_instance;
      }

      public function query($sql, $darams = array())
      {
        $this->_error = false;
        if($this->_query = $this->_pdo->prepare($sql))
        { $x = 1;
          if(count($darams))
          { foreach($darams as $param)
            { $this->_query->bindValue($x, $param);
              $x++;
            }
          }
          if($this->_query->execute())
          { $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);

            $this->_count = $this->_query->rowCount();
          }
          else      //an error has occured in SQL query
          { $this->_error = true;
          }
        }
    return $this;
      }

public function action($action, $table, $where = array())
{ if(count($where) === 3)    //field, operator, value
         { $operators = array('=', '>', '<', '>=', '<=');

           $field    = $where[0];
           $operator = $where[1];
           $value    = $where[2];

           if(in_array($operator, $operators))
           { $sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?";
             if(!$this->query($sql, array($value))->error())
             { return $this;      //no error return $this
             }
           }
         }
         return false;
       }

       public function get($table, $where)
       { return $this->action('SELECT *', $table, $where);
       }

       public function error()
       { return $this->_error;
       }

       public function count()
       { return $this->_count;
       }
      
       public function results()
       { return $this->_results;
       }

       public function first()
       { return $this->results()[0];
       }

 I have debugged the program as far as I could. The problem lies in the following function:

public function query($sql, $darams = array())
      {
        $this->_error = false;
        if($this->_query = $this->_pdo->prepare($sql))
        { $x = 1;
          if(count($darams))
          { foreach($darams as $param)
            { $this->_query->bindValue($x, $param);
              $x++;
            }
          }
          if($this->_query->execute())
          { $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);

            $this->_count = $this->_query->rowCount();
          }
          else      //an error has occured in SQL query
          { $this->_error = true;
          }
        }
    return $this;
      }

 When line "if($this->_query->execute())" is encountered program does not execute and null is returned. I have taken bits of this function from the internet and have put it together with my code. That's where the problem lies. Is there any way query(), or if need be any other function, can be altered, within context of class DB, so that query() returns an object of class DB which can be used in find()? Will be very grateful for all assistance.

Link to comment
Share on other sites

if you are certain that the code reaches the if($this->_query->execute()) statement (it would be returning a false, rather than a null on an error) and you just want to debug why it is failing (rather than to implement the error handling i suggested above), you can use print_r($this->_query->errorInfo()); in your else { ... } logic to find out what error is occurring.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.