简体   繁体   English

破译“记住我”上的堆栈跟踪错误 Function

[英]Deciphering a Stack Trace Error on “Remember Me” Function

I have received my first stack trace error on a PHP beginners CRUD educational project.我收到了关于 PHP 初学者 CRUD 教育项目的第一个堆栈跟踪错误。 Since I am a newbie, I am having trouble with it.由于我是新手,所以我遇到了麻烦。 After many hours of research I believe I may have narrowed down the error to my logout method, (although this is merely my opinion).经过数小时的研究,我相信我可能已经将错误范围缩小到我的注销方法(尽管这只是我的观点)。 If someone can help me correct my error I would greatly appreciate it.如果有人可以帮助我纠正我的错误,我将不胜感激。 I will attach some of my code here.我将在这里附上我的一些代码。 Since I am not exactly sure where the error lies, I may have left something out.由于我不确定错误在哪里,所以我可能遗漏了一些东西。 If that is the case I am more than happy to supply more code.如果是这样的话,我很乐意提供更多代码。 Thank you in advance.先感谢您。

My error occurs when I click the logout button;单击注销按钮时出现错误;

Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error in C:\xampp\htdocs\test_site.com\classes\db.php:51 Stack trace: #0 C:\xampp\htdocs\test_site.com\classes\db.php(51): PDOStatement->fetchAll(5) #1 C:\xampp\htdocs\test_site.com\classes\db.php(77): DB->query('DELETE FROM use...', Array) #2 C:\xampp\htdocs\test_site.com\classes\db.php(90): DB->action('DELETE', 'users_session', Array) #3 C:\xampp\htdocs\test_site.com\classes\user.php(243): DB->delete('users_session', Array) #4 C:\xampp\htdocs\test_site.com\logout.php(5): User->logout() #5 {main} thrown in C:\xampp\htdocs\test_site.com\classes\db.php on line 51 Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error in C:\xampp\htdocs\test_site.com\classes\db.php:51 Stack trace: #0 C:\xampp\htdocs\test_site.com\classes\ db.php(51): PDOStatement->fetchAll(5) #1 C:\xampp\htdocs\test_site.com\classes\db.php(77): DB->query('DELETE FROM use...',数组)#2 C:\xampp\htdocs\test_site.com\classes\db.php(90): DB->action('DELETE', 'users_session', 数组)#3 C:\xampp\h com\classes\user.php(243): DB->delete('users_session', Array) #4 C:\xampp\htdocs\test_site.com\logout.php(5): User->logout() #5 {main} 在第 51 行抛出 C:\xampp\htdocs\test_site.com\classes\db.php

If I comment out this code;如果我注释掉这段代码;

 $this->_db->delete('users_session', array('user_id', '=', $this->data()->id)); 

I do not get the fatal error.我没有得到致命错误。 However, I am unable to delete the entry that was made in the database to retain the hash for the 'remember me' cookie.但是,我无法删除在数据库中创建的条目以保留“记住我”cookie 的 hash。

According to the stack trace error and everything that I have tried, I keep getting this line as some sort of problem.根据堆栈跟踪错误和我尝试过的所有内容,我一直将此行视为某种问题。

 $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);

I do not know why I am having an issue here.我不知道为什么我在这里遇到问题。 I know this error seems huge and unmanageable but I am hoping someone here has an eye for these stack trace problems and can help me with this issue.我知道这个错误似乎很大且难以管理,但我希望这里有人能注意到这些堆栈跟踪问题,并能帮助我解决这个问题。 Thanks again.再次感谢。

enter code here
 /////////////////////////////////////////////////////////// 


  <?php     
     require_once 'corefiles/initiation.php';       

     if(Input::exists()) {
    if(Token::check(Input::get('token'))) {
        
        $validate = new Validate();
        $validation = $validate->check($_POST, array(
            'username' => array('required' => true),
            'password' => array('required' => true)
        ));
        
        if($validation->passed()) {
            $user = new User();
            
            $remember = (Input::get('remember') === 'on') ? true : false;                
            $login = $user->login(Input::get('username'), Input::get('password'), $remember);
            
            if($login) {
                Redirect::redirectto('index.php');                                  
            } else {
                echo '<p>Sorry, logging in failed.</p>';
            }
            
        } else {
            foreach($validation->errors() as $error) {
                echo $error, '<br>';
            }
        }           
    }
}


 <form action="" method="post">
   <div class="field">
       <label for="username">Username</label>
       <input type="text" name="username" id="username" autocomplete="off">
   </div>

   <div class="field">
       <label for="password">Password</label>
        <input type="password" name="password" id="password">   
   </div>   

   <div class="field">
      <label for="remember">
        <input type="checkbox" name="remember" id="remember"> Remember me
      </label>
    </div>

    <input type="hidden" name="token" value="<?php echo Token::generate(); ?>">
    <input type="submit" value="Log in">
 </form>

 ////////////////////////////////////////////////////////////
class User {
    private $_db,
            $_data,
            $_sessionName,
            $_cookieName,
            $_isLoggedIn;               
    
    public function __construct($user = null) {
        $this->_db = DB::getInstance();             
        
        $this->_sessionName = Config::get('session/session_name');
        $this->_cookieName = Config::get('remember/cookie_name');
        
        if(!$user) {
            if(Session::exists($this->_sessionName)) {
                $user = Session::get($this->_sessionName);
                
                if($this->find($user)) {
                    $this->_isLoggedIn = true;
                } 
            }
        } else {
            $this->find($user);
        }
    }

     public function logout() { 
        // THIS LINE IS WHAT I BELIEVE IS THE PROBLEM. IF COMMENTED OUT I CAN LOGOUT HOWEVER
        // THE HASH IN THE DATABASE DOES NOT GET DELETED.               
        $this->_db->delete('users_session', array('user_id', '=', $this->data()->id));            
        Session::delete($this->_sessionName);
        Cookie::delete($this->_cookieName);           
    }

/////////////////////////////////////////////////////////////    
class DB {
    private static $_instance = null;
    private $_pdo = null,
            $_query = null,
            $_error = false,
            $_results = null,
            $_count = 0;
    
    public $debug = true;
    
    private function __construct() {
        try {
            $this->_pdo = new PDO('mysql:host=' . Config::get('mysql/host') . ';dbname=' . 
            Config::get('mysql/db'), Config::get('mysql/username'), Config::get('mysql/password'));
            
            if($this->debug) {
                $this->_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            }
                            
        } catch(PDOException $e) {
            die($this->debug ? $e->getMessage() : '');
        }           
    }
    public function query($sql, $params = array()) {
        $this->_error = false;
        if($this->_query = $this->_pdo->prepare($sql)) {                
            $x = 1;
            if(count($params)) {
                foreach($params as $param) {
                    $this->_query->bindValue($x, $param);
                    $x++;                       
                }                   
            }               
            
            if($this->_query->execute()){
                // THIS "FETCH" CODE MAY BE AN ISSUE AS WELL. 
                //$this->_results = $this->_query->fetchObject();
                $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);//THIS IS db.php line 51
                
                
                $this->_count = $this->_query->rowCount();    
                
            } else {
                $this->_error = true;
            }
        }
        
        return $this;
    }
     public function action($action, $table, $where = array()) {
        if(count($where) === 3) {
            $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;
                }
            }
        }
        return false;
    }
    
    public function get($table, $where) {
        return $this->action('SELECT *', $table, $where);
    }
    
    public function delete($table, $where) {
        return $this->action('DELETE', $table, $where);
    }


    /////////////////////////////////////////////////////
    //Logout script
        require_once 'core/init.php';       

        $user = new User();
        $user->logout();
         //var_dump( $user->logout() );

         //redirect script
        Redirect::redirectto('index.php');   

You're doing a fetchAll after a delete query.您在删除查询后执行fetchAll

Try checking how many results are returned before calling fetchAll in the DB query method and see if that fixes the issue.尝试在 DB 查询方法中调用 fetchAll 之前检查返回了多少结果,看看是否能解决问题。

public function query($sql, $params = array()) {
    $this->_error = false;
    if($this->_query = $this->_pdo->prepare($sql)) {                
        $x = 1;
        if(count($params)) {
            foreach($params as $param) {
                $this->_query->bindValue($x, $param);
                $x++;                       
            }                   
        }               
        
        if($this->_query->execute()){
            if(substr($sql, 0, 6) === "SELECT"){
                $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
            } else {
                 $this->_results = null;
            }  
            $this->_count = $this->_query->rowCount();
        } else {
            $this->_error = true;
        }
    }
    
    return $this;
}

your " Fatal Error " is an " Uncaught PDOException ".您的“致命错误”是“未捕获的PDOException ”。 What this is is that your PDO code should be wrapped in a try{...}catch() block.这是因为您的 PDO 代码应该包含在try{...}catch()块中。 For ease you can simply put each PDO call into a try {... } wrapper and then catch as follows:为方便起见,您可以简单地将每个 PDO 调用放入try {... }包装器中,然后按如下方式捕获:

try {
    /* Or whatever DB call you make */ 
    $this->_db->delete('users_session', array('user_id', '=', $this->data()->id)); 
} 
catch(\Exception $ex){
    error_log("An Exception was caught! :".print_r($ex,true));
}

It is usually easiest to simply put a catch all global Exception ( \Exception ) as exampled above, rather than a multitude of different specific exceptions, but the option is there in the code for once you're more familiar with this concept.通常最简单的方法是简单地放置一个捕获所有全局异常 ( \Exception ),而不是许多不同的特定异常,但是一旦您更熟悉这个概念,代码中就会出现选项。

This will give you basic feedback when an action (such as your delete) fails, and why it failed (in this case written to your PHP error log).这将在操作(例如删除)失败时为您提供基本反馈,以及失败的原因(在这种情况下写入您的 PHP 错误日志)。

This will not solve the core issue ( You're doing a fetchAll after a delete query. ) but will stop Fatal Errors being generated and breaking your application.这不会解决核心问题(您在删除查询后执行 fetchAll。 )但会停止生成致命错误并破坏您的应用程序。 You can then handle this more appropriately such as outputting a message to the user.然后,您可以更适当地处理此问题,例如向用户输出消息。

The PHP manual has a lot of useful background and structure on how to implement effective Exception handling in PHP. PHP 手册有很多有用的背景和结构,说明如何在 PHP 中实现有效的异常处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM