Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 8 of 8
  1. #1
    New Coder
    Join Date
    Jan 2013
    Location
    Texas, USA
    Posts
    35
    Thanks
    5
    Thanked 0 Times in 0 Posts

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

    I can't seem to get this to work. I'm newer to oop and classes and such. I'm using a sql wrapper (yes I know some don't approve) because it's easier to query the database imo. Its class is "db" and extends PDO. I have a "page security" script here:

    PHP Code:
    class PAGESECURITY {
        private 
    $db null;
        private 
    $bindemail null;
        private 
    $updateVals null;
        private 
    $updateOffline null;
        private 
    $results null;
        private 
    $row null;
        private 
    $date null;
        private 
    $currentDate null;
        private 
    $futureDate null;
        private 
    $formatDate null;
        private 
    $getEmailBind null;
        
        public function 
    __construct()
        {
            
    // start the session
            
    session_start();
            
            
    $this->checkUser();
        }
        
        private function 
    checkUser()
        {
            if (!isset(
    $_SESSION['valid']) || $_SESSION['u_name'] == '' || $_SESSION['sess_id'] == '')
            {
                
    header('location:index.php?error=login');
                die();
            }else
            {
                
    //require necessary files
                
    require_once('config/dbconfig.php');
                require_once(
    'classes/class.mysqli.php');
                
                
    //initiate connection
                
    $this->db = new db("mysql:host=$db_host;dbname=$db_name"$db_user$db_pass);
                
    $this->db->setErrorCallbackFunction("errorHandler");
                
                
    //set up bind variables
                
    $bind = array(
                    
    ":usess" => $_SESSION['sess_id']
                );

                
    //query database
                
    $results $this->db->select('users','sessid=:usess',$bind,'sessid','','');
                
                if (
    count($results) > 0)
                {
                    foreach(
    $results as $row)
                    {
                        if(
    $_SESSION['sess_id'] != $row['sessid'])
                        {    
                            
    // session expired or wrong
                            
    header('location:index.php?error=login');
                            exit;
                        }
                    }
                }
                
                
    // set the sessions to expire in 20 minutes
                
    session_cache_expire(20);
                
                
    // set the inactive time
                
    $inactive 1200;
                
                
    // set the users session time to variable
                
    $session_life time() - $_SESSION['start'];
                
                
    // check and see if it's expired
                
    if ($session_life $inactive)
                {
                    
    // session expired
                    
    header('location:index.php?error=login');
                    exit;
                }
                
                
    // reset the session start time for each loaded page
                
    $_SESSION['start'] = time();
                
                
    //set up bind variables
                
    $bind = array(
                    
    ":uemail" => $_SESSION['u_email']
                );

                
    // set up vars to update in db
                
    $insVal = array(
                    
    'lastactive' => date('Y-m-d H:i:s')
                );

                
    // update last login in database
                
    $putIn $this->db->update("users"$insVal,'email=:uemail',$bind);
            }
        }
        
        public function 
    __destruct()
        {
            
    //kill object connection
            
    unset($this->db);
        }

    It works great. Now of course I need to query the database more than once some times, so to grab users online I have this:

    PHP Code:
    class WHOSONLINE {
        private 
    $db null;
        private 
    $bindemail null;
        private 
    $updateVals null;
        private 
    $updateOffline null;
        private 
    $results null;
        private 
    $row null;
        private 
    $date null;
        private 
    $currentDate null;
        private 
    $futureDate null;
        private 
    $formatDate null;
        private 
    $getEmailBind null;
        
        public function 
    __construct()
        {
            
    //require necessary files
            
    require_once('config/dbconfig.php');
            require_once(
    'classes/class.mysqli.php');
            
            
    //initiate connection
            
    $this->db = new db("mysql:host=$db_host;dbname=$db_name"$db_user$db_pass);
            
    $this->db->setErrorCallbackFunction("errorHandler");

            
    $this->getOnlineUsers();
        }
        
        private function 
    getOnlineUsers()
        {
            
    //set up bind variables
            
    $bindemail = array(
                
    ":uemail" => $_SESSION['u_name']
            );

            
    // set up update values
            
    $updateVals = array(
                
    'isonline' => 1,
                
    'lastactive' => date('Y-m-d H:i:s')
            );

            
    // set to update values for offline
            
    $updateOffline = array(
                
    'isonline' => 0,
                
    'lastactive' => date('Y-m-d H:i:s'),
                
    'sessid' => null
            
    );

            
    // update active user
            
    $this->db->update('users'$updateVals'email = :uemail'$bindemail);

            
    // get list of active users
            
    $results $this->db->select('users','isonline=1','','id, email, firstname, lastactive','','');
            
            
    // catch all the users and output
            
    if (count($results) > 0)
            {
                foreach(
    $results as $row)
                {
                    
    // set up the date
                    
    $date $row['lastactive'];
                    
    $currentDate strtotime($date);
                    
    $futureDate $currentDate+(60*5);
                    
    $formatDate date("Y-m-d H:i:s"$futureDate);
                    
                    
    // check the date on each record that says is online. If not, update that record to offline like logout
                    
    if ($formatDate date('Y-m-d H:i:s'))
                    {
                        echo 
    '<li><a id="userid" href="userprofile.php?id=' .$row['id']. '" alt="Last Active: ' .$row['lastactive']. '">' .$row['firstname']. '</a></li>';
                    }else
                    {
                        
    //set up bind variables
                        
    $getEmailBind = array(
                            
    ":rowemail" => $row['email']
                        );
                        
                        
    // update that field in database for inactive user
                        
    $this->db->update('users'$updateOffline'email = :rowemail'$getEmailBind);
                    }
                }
            }
        }
        public function 
    __destruct()
        {
            
    //kill object connection
            
    unset($this->db);
        }

    But I get this error:
    PHP Code:
    Fatal errorCall to a member function setErrorCallbackFunction() on a non-object in /home/imengi86/public_html/fileshare/classes/class.whosonline.php on line 23 
    Both these classes are being "require" on the same page, but again, I'm going to need many queries to the database. I don't seem to understand why it's so. I know what it means, it's not an object, but I'm setting it as an object. I know it has something to do, most likely, with me setting another already, but there must be some way to make this work...? I also want to stay away from singleton. From what I've read and understand it's incredibly bad in the end...


    Edit: It also doesn't matter if I use $connect instead of $db in the second class. Just to add...
    Last edited by gkjr1; 02-10-2013 at 08:54 AM. Reason: New Info

  • #2
    New Coder
    Join Date
    Jan 2013
    Location
    Texas, USA
    Posts
    35
    Thanks
    5
    Thanked 0 Times in 0 Posts
    I've tried everything I can think of. The only way I can get it to work is NOT using it as an actual class, and just including this code as procedure style scripting.

    I know I've gotta be doing something wrong with the class for it to be doing this, as plenty of classes I've seen include other objects in them and such, I just don't get it. Like I said, the first class works fine, it's just when I try to create another database object in a different class, where they both are included on the same page. Please someone help me out...

  • #3
    New Coder
    Join Date
    Jan 2013
    Location
    Texas, USA
    Posts
    35
    Thanks
    5
    Thanked 0 Times in 0 Posts
    Never mind. I got it. If there's a better way please let me know.


    I simply included the connection to the database in the config instead of a class and made an object. I then included that config in every single page I will need to access the database. From there, every class that needs to use the database (and each class being included on the page with the config included first) passes the global $db, which is the object, into a private function in the class.

    If there is some sort of security issue in this aspect, or a more efficient way to do this please let me know. It's all I could get to work.

  • #4

  • #5
    New Coder
    Join Date
    Jan 2012
    Location
    Latvia
    Posts
    65
    Thanks
    8
    Thanked 2 Times in 2 Posts
    It seems that this line is making the Error:

    PHP Code:
    $this->db->setErrorCallbackFunction("errorHandler"); 
    You are trying to replace the function for Handling Errors, and it seems to be invalid. Try to remove this line, and see if it works.
    Last edited by WingTsun; 02-11-2013 at 08:49 PM.
    "Be formless... shapeless, like water. Now you put water into a cup, it becomes the cup. You pour water into a bottle; it becomes the bottle. You put water into a teapot; it becomes the teapot. Now water can flow, or creep or drip or crash! Be water, my friend..." by Bruce Lee

  • #6
    New Coder
    Join Date
    Jan 2013
    Location
    Texas, USA
    Posts
    35
    Thanks
    5
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by gvre View Post
    It's better to use autoloading and dependency injection.
    I briefly read over those. Is it basically just a code to load all or select classes on a page? And dependency injection is only putting in the classes needed? If someone could explain in layman terms please...

    Quote Originally Posted by WingTsun View Post
    It seems that this line is making the Error:

    PHP Code:
    $this->db->setErrorCallbackFunction("errorHandler"); 
    You are trying to replace the function for Handling Errors, and it seems to be invalid. Try to remove this line, and see if it works.
    I believe I have tried this already and it just moved to the next call on the object, but I will try again when I get a chance. Just taking a break in between homework. Stupid college getting in the way of my website lol.

  • #7
    Regular Coder
    Join Date
    May 2011
    Posts
    240
    Thanks
    1
    Thanked 56 Times in 55 Posts
    Autoloading Classes

    Many developers writing object-oriented applications create one PHP source file per class definition. One of the biggest annoyances is having to write a long list of needed includes at the beginning of each script (one for each class).

    In PHP 5, this is no longer necessary. You may define an __autoload() function which is automatically called in case you are trying to use a class/interface which hasn't been defined yet. By calling this function the scripting engine is given a last chance to load the class before PHP fails with an error.
    For dependency injection, read the following presentations.
    http://www.procata.com/talks/phptek-...dependency.pdf
    http://fabien.potencier.org/media/ta...y-ipc-2008.pdf

  • #8
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    __autoload is a bit of an ol' school method already. spl_autoload_register is much easier to work with as it effectively constructs a stack of methods to check through until one returns a valid match. That does require 5.1.2 though.
    An even easier method is if you use namespacing in PHP 5.3, suffix your extensions, and register that on the path. This is chained to the use keyword, so after an extension register and base path addition to the include path, you never need to issue a require/include for a class autoload again.

    For this actual problem though, this error doesn't make any sense for what you have. new always returns a new instance of an object OR it throws an exception. I'm not aware of any way to nullify this within the constructor. I *believe* early 5.0 gen PHP had a bug that allowed you to destroy in a constructor by unsetting $this, but I also believe that's been fixed.
    But from these lines here, you should always have an instance of the object:
    PHP Code:
            //initiate connection
            
    $this->db = new db("mysql:host=$db_host;dbname=$db_name"$db_user$db_pass);
            
    $this->db->setErrorCallbackFunction("errorHandler"); 
    The first line will assign $this->db with an instance of db, regardless of what that instance results in. If it cannot construct an instance (forced *new* construct singleton via exceptions for example), than that line would trigger an exception, which terminates the attempted construction of the WHOSONLINE object as well. When this happens, it would never attempt the setErrorCallbackFunction since it failed to construct the object properly. Here's an example of what I mean:
    PHP Code:
    class C
    {
        private 
    $conn;
        
        public function 
    __construct()
        {
            
    $this->conn = new T();
            print 
    $this->conn->method();
        }
    }

    class 
    T
    {
        private static 
    $cnt 0;
        public function 
    __construct()
        {
            if (
    self::$cnt >= 1)
            {
                throw new 
    RuntimeException('Can only have one of ' __CLASS__);
            }
            
    self::$cnt++;
        }
        public function 
    method()
        {
            return 
    __METHOD__;
        }
    }

    try
    {
       
    $c = new C();
       echo 
    '$c done.';
       
    $c2 = new C();
       echo 
    '$c2 done.';
    }
    catch (
    Exception $ex)
    {
        print 
    $ex->getMessage();

    So here $c will exist, but $c2 will not. Since it fails on the second new C(), it is impossible to make it to echo '$c2 done.'; instruction.

    Now, this all being said, they have had issues in the past with PDO not returning an object, nor throwing an exception if there were problems with connections to the databases. I wouldn't have expected that such bugs would still exist, but I do guess it depends on the version of PHP in use.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •