PHP调用非对象的函数

时间:2011-03-21 20:52:42

标签: php session-variables

我在创建会话类时遇到问题 - 我试图将数据库对象传递给它来调用它的函数但是我继续在ssession.class.php的46处获得对未定义函数的错误调用,或者像奇怪的那样这个声音,给我一个不同的错误,它呼吁一个非对象。我以为你可以将对象存储为类变量,并且不理解为什么它没有找到数据库。

<?php

include("http://www.walkingspheres.com/include/database.class.php");
include("http://www.walkingspheres.com/include/mailer.php");
include("http://www.walkingspheres.com/include/form.php");

class Session
{
   var $username;     //Username given on sign-up
   var $sessionid;    //Random value generated on current login
   var $userlevel;    //The level to which the user pertains
   var $time;         //Time user was last active (page loaded)
   var $logged_in;    //True if user is logged in, false otherwise
   var $userinfo = array();  //The array holding all user info
   var $url;          //The page url current being viewed
   var $referrer;     //Last recorded site page viewed
   var $database;

   /* Class constructor */
   function Session($db){
      $this->time = time();
      $this->databse = $db;
      $this->startSession();
   }

   /**
    * startSession - Performs all the actions necessary to 
    * initialize this session object. Tries to determine if the
    * the user has logged in already, and sets the variables 
    * accordingly. Also takes advantage of this page load to
    * update the active visitors tables.
    */
   function startSession(){
      session_start();   //Tell PHP to start the session

      /* Determine if user is logged in */
      $this->logged_in = $this->checkLogin();

      /**
       * Set guest value to users not logged in, and update
       * active guests table accordingly.
       */
      if(!$this->logged_in){
         $this->username = $_SESSION['username'] = GUEST_NAME;
         $this->userlevel = GUEST_LEVEL;
         $this->database->addActiveGuest($_SERVER['REMOTE_ADDR'], $this->time);
      }
      /* Update users last active timestam*/
      else{
         $this->database->addActiveUser($this->username, $this->time);
      }

      /* Remove inactive visitors from database */
      $this->database->removeInactiveUsers();
      $this->database->removeInactiveGuests();

      /* Set referrer page */
      if(isset($_SESSION['url'])){
         $this->referrer = $_SESSION['url'];
      }else{
         $this->referrer = "/";
      }

      /* Set current url */
      $this->url = $_SESSION['url'] = $_SERVER['PHP_SELF'];
   }

   /**
    * checkLogin - Checks if the user has already previously
    * logged in, and a session with the user has already been
    * established. Also checks to see if user has been remembered.
    * If so, the database is queried to make sure of the user's 
    * authenticity. Returns true if the user has logged in.
    */
   function checkLogin(){  

            /* Check if user has been remembered */
      if(isset($_COOKIE['cookname']) && isset($_COOKIE['cookid'])){
         $this->username = $_SESSION['username'] = $_COOKIE['cookname'];
         $this->sessionid   = $_SESSION['sessionid']   = $_COOKIE['cookid'];
      }

      /* Username and sessionid have been set and not guest */
      if(isset($_SESSION['username']) && isset($_SESSION['sessionid']) &&
         $_SESSION['username'] != GUEST_NAME){
         /* Confirm that username and sessionid are valid */
         if($this->database->confirmSessionID(
                    $_SESSION['username'],$_SESSION['sessionid'])!= 0)
         {
            /* Variables are incorrect, user not logged in */
            unset($_SESSION['username']);
            unset($_SESSION['sessionid']);
            return false;
         }

         /* User is logged in, set class variables */
         $this->userinfo  = $this->database->getUserInfo($_SESSION['username']);
         $this->username  = $this->userinfo['username'];
         $this->sessionid    = $this->userinfo['sessionid'];
         $this->userlevel = $this->userinfo['userlevel'];
         return true;
      }

      /* User not logged in */
      else{
         return false;
      }
   }

   /**
    * login - The user has submitted his username and password
    * through the login form, this function checks the authenticity
    * of that information in the database and creates the session.
    * Effectively logging in the user if all goes well.
    */
   function login($subuser, $subpass, $subremember){
      $form;  //The database and form object

      /* Username error checking */
      $field = "user";  //Use field name for username
      if(!$subuser || strlen($subuser = trim($subuser)) == 0){
         $form->setError($field, "* Username not entered");
      }
      else{
         /* Check if username is not alphanumeric */
         if(!preg_match("/^([0-9a-z])*$/", $subuser)){
            $form->setError($field, "* Username not alphanumeric");
         }
      }

      /* Password error checking */
      $field = "pass";  //Use field name for password
      if(!$subpass){
         $form->setError($field, "* Password not entered");
      }

      /* Return if form errors exist */
      if($form->num_errors > 0){
         return false;
      }

      /* Checks that username is in database and password is correct */
      $subuser = stripslashes($subuser);
      $result = $this->database->confirmUserPass($subuser, md5($subpass));

      /* Check error codes */
      if($result == 1){
         $field = "user";
         $form->setError($field, "* Username not found");
      }
      else if($result == 2){
         $field = "pass";
         $form->setError($field, "* Invalid password");
      }

      /* Return if form errors exist */
      if($form->num_errors > 0){
         return false;
      }

      /* Username and password correct, register session variables */
      $this->userinfo  = $this->database->getUserInfo($subuser);
      $this->username  = $_SESSION['username'] = $this->userinfo['username'];
      $this->sessionid    = $_SESSION['sessionid']   = $this->generateRandID();
      $this->userlevel = $this->userinfo['userlevel'];

      /* Insert sessionid into database and update active users table */
      $this->database->updateUserField($this->username, "sessionid", $this->sessionid);
      $this->database->addActiveUser($this->username, $this->time);
      $this->database->removeActiveGuest($_SERVER['REMOTE_ADDR']);

      /**
       * This is the cool part: the user has requested that we remember that
       * he/she logged in, so we set two cookies. One to hold his/her username,
       * and one to hold his/her random value sessionid. It expires by the time
       * specified in definitions.php. Now, next time he/she comes to our site, we will
       * log him/her in automatically, but only if she/he didn't log out before they left
      */
      if($subremember){
         setcookie("cookname", $this->username, time()+COOKIE_EXPIRE, COOKIE_PATH);
         setcookie("cookid",   $this->sessionid,   time()+COOKIE_EXPIRE, COOKIE_PATH);
      }

      /* Login completed successfully */
      return true;
   }

   /**
    * logout - Gets called when the user wants to be logged out of the
    * website. It deletes any cookies that were stored on the users
    * computer as a result of him wanting to be remembered, and also
    * unsets session variables and demotes his user level to guest.
    */
   function logout(){
      /**
       * Delete cookies - the time must be in the past,
       * so just negate what you added when creating the
       * cookie.
       */
      if(isset($_COOKIE['cookname']) && isset($_COOKIE['cookid'])){
         setcookie("cookname", "", time()-COOKIE_EXPIRE, COOKIE_PATH);
         setcookie("cookid",   "", time()-COOKIE_EXPIRE, COOKIE_PATH);
      }

      /* Unset PHP session variables */
      unset($_SESSION['username']);
      unset($_SESSION['sessionid']);
      unset($_SESSION['error_array']);
      unset($_SESSION['value_array']);
      unset($_SESSION['regsuccess']);

      /* Reflect fact that user has logged out */
      $this->logged_in = false;

      /**
       * Remove from active users table and add to
       * active guests tables.
       */
      $this->database->removeActiveUser($this->username);
      $this->database->addActiveGuest($_SERVER['REMOTE_ADDR'], $this->time);

      /* Set user level to guest */
      $this->username  = GUEST_NAME;
      $this->userlevel = GUEST_LEVEL;
   }

   /**
    * register - Gets called when the user has just submitted the
    * registration form. Determines if there were any errors with
    * the entry fields, if so, it records the errors and returns
    * 1. If no errors were found, it registers the new user and
    * returns 0. Returns 2 if registration failed.
    */

   function register($subuser,$subpass,$subemail,$c_pass,$c_email,$home,$bday){
      global $form, $mailer;  //The database, form and mailer object

      /* Username error checking */
      $field = "user";  //Use field name for username
      $subuser=trim($subuser);
      if(strlen($subuser) == 0){
         $form->setError($field, "* Username not entered");
      }
      else{
         /* Spruce up username, check length */
         $subuser = stripslashes($subuser);
         if(strlen($subuser) < 5){
            $form->setError($field, "* Username below 5 characters");
         }
         else if(strlen($subuser) > 30){
            $form->setError($field, "* Username above 30 characters");
         }
         /* Check if username is not alphanumeric */
         else if(!preg_match("/^([0-9a-z])+$/", $subuser)){
            $form->setError($field, "* Username not alphanumeric");
         }
         /* Check if username is reserved */
         else if(strcasecmp($subuser, GUEST_NAME) == 0){
            $form->setError($field, "* Username reserved word");
         }
         /* Check if username is already in use */
         else if($this->database->usernameTaken($subuser)){
            $form->setError($field, "* Username already in use");
         }
         /* Check if username is banned */
         else if($this->database->usernameBanned($subuser)){
            $form->setError($field, "* Username banned");
         }
      }

      /* Password error checking */
      $field = "password";  //Use field name for password
      $subpass=trim($subpass);
      $c_pass=trim($c_pass);
      if(strlen($subpass)==0 || strlen($c_pass)==0){
         $form->setError($field, "* Password not entered");
      }
      else{
         /* Spruce up password and check length*/
         if(strlen($subpass) < 4){
            $form->setError($field, "* Password too short");
         }
         /* Check if password is not alphanumeric */
         else if(!preg_match("/^([0-9a-z])+$/", $subpass)){
            $form->setError($field, "* Password not alphanumeric");
         }
         /* Check if both passwords entered match */
         else if(strcmp($subpass,$c_pass) != 0){
            $form->setError($field, "* Passwords don't match");
     }
      }

      /* Email error checking */
      $field = "email";  //Use field name for email
      $subemail=trim($subemail);
      $c_email=trim($c_email);
      if(strlen($subemail) == 0){
         $form->setError($field, "* Email not entered");
      }
      else{
         /* Check if valid email address */
         $regex = "/^[_+a-z0-9-]+(\.[_+a-z0-9-]+)*"
                 ."@[a-z0-9-]+(\.[a-z0-9-]{1,})*"
                 ."\.([a-z]{2,}){1}$/";
         if(!preg_match($regex,$subemail)){
            $form->setError($field, "* Email invalid");
         }
         else if(strcmp($subemail,$c_email)!=0){
           $form->setError($field, "* Emails don't match");
     }
      }

      /* Errors exist, have user correct them */
      if($form->num_errors > 0){
         return 1;
      }
      /* No errors, add the new account to the db */
      else{
        $home=trim($home);
        $bday=trim($bday);
         if($this->database->addNewUser($subuser, md5($subpass),$subemail,$home,$bday)){
            if(EMAIL_WELCOME){
               $mailer->sendWelcome($subuser,$subemail,$subpass);
            }
            return 0;  //New user added succesfully
         }else{
            return 2;  //Registration attempt failed
         }
      }
   }

   /**
    * editAccount - Attempts to edit the user's account information
    * including the password, which it first makes sure is correct
    * if entered, if so and the new password is in the right
    * format, the change is made. All other fields are changed
    * automatically.
    */
   function editAccount($subcurpass, $subnewpass, $subemail){
      global $form;  //The database and form object
      /* New password entered */
      if($subnewpass){
         /* Current Password error checking */
         $field = "curpass";  //Use field name for current password
         if(!$subcurpass){
            $form->setError($field, "* Current Password not entered");
         }
         else{
            /* Check if password too short or is not alphanumeric */
            $subcurpass = stripslashes($subcurpass);
            if(strlen($subcurpass) < 4 ||
               !preg_match("/^([0-9a-z])+$/", ($subcurpass = trim($subcurpass)))){
               $form->setError($field, "* Current Password incorrect");
            }
            /* Password entered is incorrect */
            if($this->database->confirmUserPass($this->username,md5($subcurpass)) != 0){
               $form->setError($field, "* Current Password incorrect");
            }
         }

         /* New Password error checking */
         $field = "newpass";  //Use field name for new password
         /* Spruce up password and check length*/
         $subpass = stripslashes($subnewpass);
         if(strlen($subnewpass) < 4){
            $form->setError($field, "* New Password too short");
         }
         /* Check if password is not alphanumeric */
         else if(!preg_match("/^([0-9a-z])+$/", ($subnewpass = trim($subnewpass)))){
            $form->setError($field, "* New Password not alphanumeric");
         }
      }
      /* Change password attempted */
      else if($subcurpass){
         /* New Password error reporting */
         $field = "newpass";  //Use field name for new password
         $form->setError($field, "* New Password not entered");
      }

      /* Email error checking */
      $field = "email";  //Use field name for email
      if($subemail && strlen($subemail = trim($subemail)) > 0){
         /* Check if valid email address */
         $regex = "/^[_+a-z0-9-]+(\.[_+a-z0-9-]+)*"
                 ."@[a-z0-9-]+(\.[a-z0-9-]{1,})*"
                 ."\.([a-z]{2,}){1}$/";
         if(!preg_match($regex,$subemail)){
            $form->setError($field, "* Email invalid");
         }
         $subemail = stripslashes($subemail);
      }

      /* Errors exist, have user correct them */
      if($form->num_errors > 0){
         return false;  //Errors with form
      }

      /* Update password since there were no errors */
      if($subcurpass && $subnewpass){
         $this->database->updateUserField($this->username,"password",md5($subnewpass));
      }

      /* Change Email */
      if($subemail){
         $this->database->updateUserField($this->username,"email",$subemail);
      }

      /* Success! */
      return true;
   }

   /**
    * isAdmin - Returns true if currently logged in user is
    * an administrator, false otherwise.
    */
   function isAdmin(){
      return ($this->userlevel == ADMIN_LEVEL ||
              $this->username  == ADMIN_NAME);
   }

   /**
     * confirmFriends - pre: sessionid, requestingid
     * returns true if they are both friends
     * else returns false
     */
   function confirmFriends($uid,$rid){
     $q = "SELECT name FROM friends WHERE userid_fk='$uid' AND fid='$rid' ";
     $res->$this->database->query($q);
     if($res){  //exists
       return true;
     }
     else
       return false;
   } 

   /**
    * generateRandID - Generates a string made up of randomized
    * letters (lower and upper case) and digits and returns
    * the md5 hash of it to be used as a sessionid.
    */
   function generateRandID(){
      return md5($this->generateRandStr(16));
   }

   /**
    * generateRandStr - Generates a string made up of randomized
    * letters (lower and upper case) and digits, the length
    * is a specified parameter.
    */
   function generateRandStr($length){
      $randstr = "";
      for($i=0; $i<$length; $i++){
         $randnum = mt_rand(0,61);
         if($randnum < 10){
            $randstr .= chr($randnum+48);
         }else if($randnum < 36){
            $randstr .= chr($randnum+55);
         }else{
            $randstr .= chr($randnum+61);
         }
      }
      return $randstr;
   }
}

/**
 * Initialize session object - This must be initialized before
 * the form object because the form uses session variables,
 * which cannot be accessed unless the session has started.
 */

$session = new Session($database);

/* Initialize form object */
$form = new Form();
?>

我的另一个问题,下面你会看到数据库类,但我有session_start();在我的所有页面的顶部,由于某种原因,数据库和会话之间的混合拒绝实际注册或登录任何人。也许有人能找出原因?

<?php

require_once("http://www.walkingspheres.com/definitions.php");

class MySQLDB
{
   var $connection;         //The MySQL database connection
   var $num_active_users;   //Number of active users viewing site
   var $num_active_guests;  //Number of active guests viewing site
   var $num_members;        //Number of signed-up users
   /* Note: call getNumMembers() to access $num_members! */

   /* Class constructor */
   function MySQLDB(){
      /* Make connection to database */
      $this->connection = mysql_connect("localhost","name","pass") or die(mysql_error());
      mysql_select_db("pen15_users", $this->connection) or die(mysql_error());

      /**
       * Only query database to find out number of members
       * when getNumMembers() is called for the first time,
       * until then, default value set.
       */
      $this->num_members = -1;

      if(TRACK_VISITORS){
         /* Calculate number of users at site */
         $this->calcNumActiveUsers();

         /* Calculate number of guests at site */
         $this->calcNumActiveGuests();
      }
   }

   /**
    * confirmUserPass - Checks whether or not the given
    * username is in the database, if so it checks if the
    * given password is the same password in the database
    * for that user. If the user doesn't exist or if the
    * passwords don't match up, it returns an error code
    * (1 or 2). On success it returns 0.
    */
   function confirmUserPass($username, $password){
      /* Verify that user is in database */
      $q = "SELECT password FROM members WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      if(!$result || (mysql_numrows($result) < 1)){
         return 1; //Indicates username failure
      }

      /* Retrieve password from result, strip slashes */
      $dbarray = mysql_fetch_array($result);
      $dbarray['password'] = stripslashes($dbarray['password']);
      $password = stripslashes($password);

      /* Validate that password is correct */
      if($password == $dbarray['password']){
         return 0; //Success! Username and password confirmed
      }
      else{
         return 2; //Indicates password failure
      }
   }

   /**
    * confirmSessionID - Checks whether or not the given
    * username is in the database, if so it checks if the
    * given userid is the same userid in the database
    * for that user. If the user doesn't exist or if the
    * userids don't match up, it returns an error code
    * (1 or 2). On success it returns 0.
    */
  public function confirmSessionId($username, $sessionid){
      /* Add slashes if necessary (for query) */
      if(!get_magic_quotes_gpc()) {
          $username = addslashes($username);
      }

      /* Verify that user is in database */
      $q = "SELECT sessionid FROM members WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      if(!$result || (mysql_numrows($result) < 1)){
         return 1; //Indicates username failure
      }

      /* Retrieve id from result, strip slashes */
      $dbarray = mysql_fetch_array($result);

      /* Validate that sessionid is correct */
      if($sessionid == $dbarray['sessionid']){
         return 0; //Success! Username and session confirmed
      }
      else{
         return 2; //Indicates userid invalid
      }
   }

   /**
    * usernameTaken - Returns true if the username has
    * been taken by another user, false otherwise.
    */
   function usernameTaken($username){
      $q = "SELECT username FROM members WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      return (mysql_numrows($result) > 0);
   }

   /**
    * usernameBanned - Returns true if the username has
    * been banned by the administrator.
    */
   function usernameBanned($username){
      if(!get_magic_quotes_gpc()){
         $username = addslashes($username);
      }
      $q = "SELECT username FROM banned_users WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      return (mysql_numrows($result) > 0);
   }

   /**
    * addNewUser - Inserts the given (username, password, email)
    * info into the database. Appropriate user level is set.
    * Returns true on success, false otherwise.
    */
   function addNewUser($username,$password,$email,$home,$bday){
      $time = time();
      /* If admin sign up, give admin user level */
      if(strcasecmp($username, 'pen15') == 0 ||
         strcasecmp($username, 'Charlie DeHart')==0 ){
         $ulevel = 9;
      }else{
         $ulevel = 1;
      }
      $home=trim($home);
      $bday=trim($day);
      if($home='' || $home=NULL)
        $home = 'default';

      if($bday='' || $bday=NULL)
        $bday = 'default';

      $sessionid = '1'; 

      $q = "INSERT INTO members(username, password,";
            "email, userlevel, timestamp, home, birthday, sessionid) ";
            "VALUES ('$username','$password','$email','$ulevel','$time',";
            "'$home','$bday','$sessionid')";

      return mysql_query($q, $this->connection);
   }

   /**
    * updateUserField - Updates a field, specified by the field
    * parameter, in the user's row of the database.
    */
   function updateUserField($username, $field, $value){
    $q = "UPDATE members SET ".$field." = '$value' WHERE username = '$username'";
      return mysql_query($q, $this->connection);
   }

   /**
    * getUserInfo - Returns the result array from a mysql
    * query asking for all information stored regarding
    * the given username. If query fails, NULL is returned.
    */
   function getUserInfo($username){
      $q = "SELECT * FROM members WHERE username = '$username'";
      $result = mysql_query($q, $this->connection);
      /* Error occurred, return given name by default */
      if(!$result || (mysql_numrows($result) < 1)){
         return NULL;
      }
      /* Return result array */
      $dbarray = mysql_fetch_array($result);
      return $dbarray;
   }

}

/* Create database connection */
$database = new MySQLDB;

?>

非常感谢您提供任何评论,帮助或解释,如果包含一个在底部创建新类的文件将调用构造函数。

3 个答案:

答案 0 :(得分:1)

  $this->databse = $db;

应该是$ this-&gt;数据库

要讨厌错别字吗?由于对象属性的分配没有正确完成,因此$ this-&gt;数据库为空,因此您尝试调用的函数(在本例中更多是一种方法)是未定义的。

另一方面(因为上面的评论应该解决你当前的问题):你让自己暴露在死亡之中。

function confirmUserPass($username, $password){
  /* Verify that user is in database */
  $q = "SELECT password FROM members WHERE username = '$username'";
  $result = mysql_query($q, $this->connection);

如果我使$ username成为某些你不想要的SQL的东西怎么办?这并不难。请使用mysql_escape_string(呃,我可能错误的是函数的确切名称,我现在总是使用PDO)或者将代码更改为准备好的语句。否则你将遭受SQL注入(http://en.wikipedia.org/wiki/SQL_injection)

对用户最初提交的数据库的每个单一数据输入执行相同操作(通常即使它是由用户间接提交的)

答案 1 :(得分:1)

include("http://www.walkingspheres.com/include/database.class.php");
include("http://www.walkingspheres.com/include/mailer.php");
include("http://www.walkingspheres.com/include/form.php");

糟糕!

哇,你有allow_url_fopen吗?它看起来像。或者你的错误报告水平转向了。如果这些代码行有效,then your code is exploiting an incorrect PHP setting that may be a huge security hole

include 执行代码。您是include个网址。这意味着PHP正在发出Web请求来下载这些文件。如果有人能够欺骗您的代码执行任意include,他们就可以在您的服务器上执行他们的代码,而您永远不会知道。

这些是PHP脚本。它很可能是在发出请求时执行而不是返回源代码,而是返回任何内容。那个或PHP 已正确配置,但您的错误报告级别正在隐藏问题。

请更改所有includeinclude_oncerequirerequire_once来电,以使用文件系统上的路径而不是网址。< / p>

使用以下两行代码在开发过程中调高错误报告级别

ini_set('display_errors', true);
error_reporting(-1);

我愿意打赌,提出错误报告会让PHP对你遇到的问题感到非常大声 ,从序列化问题到数据库错误。

另外,你能告诉我们你在哪里学习“Session”课程吗?这真的非常古老,人们经常遇到麻烦。它的设计很差,可能不应该在现代使用。我真的很想知道它来自哪里,所以我可以让作者 - * ahem * - 重新接受教育和/或让数据中心托管它从轨道上运行。

答案 2 :(得分:0)

(你的代码很长,我没有试过去理解它 - 但我看到有一件事感觉很奇怪)


MySQLDB类的$connection属性为resource - 因为它是mysql_connect()函数的返回值。


资源无法序列化 - 请参阅serialize()的手册页以获取参考(引用)

  

serialize()处理所有类型,除外   资源类型


我猜你的$database类的Session属性指向你的MYSQLDB类的一个实例 - 它包含一个资源。

该资源无法序列化 - 因此,它无法存储在$_SESSION中;或者,更具体地说,它无法从会话中恢复。


要解决这一特定问题,您应该在加载会话时重新连接到您的数据库 - __sleep() and __wakeup()魔术方法可能有帮助,这里。