raydona Posted November 24, 2014 Share Posted November 24, 2014 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. Quote Link to comment https://forums.phpfreaks.com/topic/292690-call-to-a-member-function-on-a-non-object/ Share on other sites More sharing options...
Barand Posted November 24, 2014 Share Posted November 24, 2014 It would seem that the query called by $this->_db->get('users', array($field, '=', $user)); failed and $data is, therefore, not a valid object. Quote Link to comment https://forums.phpfreaks.com/topic/292690-call-to-a-member-function-on-a-non-object/#findComment-1497541 Share on other sites More sharing options...
bsmither Posted November 25, 2014 Share Posted November 25, 2014 (edited) "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 November 25, 2014 by bsmither Quote Link to comment https://forums.phpfreaks.com/topic/292690-call-to-a-member-function-on-a-non-object/#findComment-1497644 Share on other sites More sharing options...
raydona Posted November 25, 2014 Author Share Posted November 25, 2014 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; } Quote Link to comment https://forums.phpfreaks.com/topic/292690-call-to-a-member-function-on-a-non-object/#findComment-1497667 Share on other sites More sharing options...
mac_gyver Posted November 26, 2014 Share Posted November 26, 2014 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. Quote Link to comment https://forums.phpfreaks.com/topic/292690-call-to-a-member-function-on-a-non-object/#findComment-1497716 Share on other sites More sharing options...
raydona Posted November 28, 2014 Author Share Posted November 28, 2014 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. Quote Link to comment https://forums.phpfreaks.com/topic/292690-call-to-a-member-function-on-a-non-object/#findComment-1497925 Share on other sites More sharing options...
mac_gyver Posted November 28, 2014 Share Posted November 28, 2014 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. Quote Link to comment https://forums.phpfreaks.com/topic/292690-call-to-a-member-function-on-a-non-object/#findComment-1497936 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.