PHP OOP PDO 错误显示

PHP OOP PDO Error Display

我正在为我的网站构建一个 OOP/PDO 登录系统,但是,当用户登录尝试失败时,我不知道如何在我的登录 class 中正确显示错误消息。另外,我想知道我的 OOP 方法是否正确。这是我使用 OOP 和 PDO 的第一个项目。如果您对我的代码有任何建议,我想听听。

login.class.php

<?php
    class Login {
        private $dbConnection;
        private $studentNumber;
        private $studentClass;
        private $errorMessage = false;

        public function __construct($dbConnection) {
            $this->dbConnection = $dbConnection->dbConnection;
        }

        public function showErrorMessage() {
            return $this->errorMessage;
        }

        public function studentLogin($studentNumber, $studentClass) {
            $this->studentNumber = $studentNumber;
            $this->studentClass = $studentClass;

            $selectStudent = $this->dbConnection->prepare("SELECT * FROM tbl_students WHERE studentNumber = :studentNumber AND studentClass = :studentClass LIMIT 1");
            $selectStudent->bindParam(':studentNumber', $this->studentNumber);
            $selectStudent->bindParam(':studentClass', $this->studentClass);
            $selectStudent->execute();

            $selectStudentCheck = $selectStudent->fetch(PDO::FETCH_ASSOC);
            if(!empty($selectStudentCheck)) {
                return true;
            }
            else {
                $this->errorMessage = "Studentnumber or class is not correct";
            }
        }
    }
?>

dbconnection.class.php

<?php
    class DatabaseConnection {
        private $DatabaseHost = "localhost";
        private $DatabaseName = "plansysteem_keuzetrainingen";
        private $userName = "root";
        private $passWord = "root";
        public $dbConnection;

        public function __construct() {
            $this->databaseConnect();
        }

        public function databaseConnect() {
            try{
                $this->dbConnection = new PDO("mysql:host=$this->DatabaseHost;dbname=$this->DatabaseName", $this->userName, $this->passWord);
                $this->dbConnection->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
            }
            catch(PDOException $e){
                print("Sorry er kan geen verbinding worden gemaakt met de database");
                file_put_contents("../errors/database.connection.errors.txt", $e->getMessage().PHP_EOL,FILE_APPEND);
                die();
            }
        }
    }
?>

登录表单

<?php
    session_start();

    include ("../classes/dbconnection.class.php");
    include ("../classes/login.class.php");

    if(isset($_POST["submitLogin"])) {
        $studentNumber = $_POST["studentNumber"];
        $studentClass = $_POST["studentClass"];

        $dbConnection = new DatabaseConnection();
        $login = new Login($dbConnection);
        if($login->studentLogin($studentNumber, $studentClass)) {
            echo "Succes";
        }
        else {
             echo "Student not found!";
        }
    }
?>
<!DOCTYPE html>
<html class="no-js" lang="nl">
    <head>
        <meta charset="UTF-8" />
        <meta name="description" content="" />
        <meta name="keywords" content="" />
        <meta name="author" content="Communication Centre" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Login Plansysteem Keuzetrainingen</title>
        <link rel="icon" type="image/png" href="../img/favicon.png" sizes="16x16 32x32" />
        <link rel="stylesheet" type="text/css" href="../css/foundation.css" />
        <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Advent+Pro" />
        <link rel="stylesheet" type="text/css" href="../css/main.css" />
        <script type="text/javascript" src="../js/vendor/modernizr.js"></script>
    </head>
    <body>

        <div class="row">
            <div class="small-12 medium-8 medium-offset-2 large-6 large-offset-3 columns">
                <h1 class="mainTitle">inloggen</h1>
            </div>
        </div>
        <form method="post">
            <div class="row">
                <div class="small-12 medium-8 medium-offset-2 large-6 large-offset-3 columns">
                    <small class="error"></small>
                </div>
            </div>
            <div class="row">
                <div class="small-12 medium-8 medium-offset-2 large-6 large-offset-3 columns">
                    <div class="row collapse">
                        <div class="small-2 medium-1 large-1 columns">
                            <span class="prefix">
                                <img src="../img/cursor_icon.png" alt="Cursor Icon" />
                            </span>
                        </div>
                        <div class="small-10 medium-11 large-11 columns">
                            <input type="text" name="studentNumber" placeholder="Studentnummer" class="placeholderBlack" />
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="small-12 medium-8 medium-offset-2 large-6 large-offset-3 columns">
                    <div class="row collapse">
                        <div class="small-2 medium-1 large-1 columns">
                            <span class="prefix">
                                <img src="../img/person_icon.png" alt="Person Icon" />
                            </span>
                        </div>
                        <div class="small-10 medium-11 large-11 columns">
                            <select name="studentClass">
                                <option value="">Selecteer Klas</option>
                                <option value="1DVTM-REG-01.P1">1DVTM-REG-01.P1</option>
                                <option value="1DVTM-REG-02.P1">1DVTM-REG-02.P1</option>
                                <option value="1DVTM-REG-03.P1">1DVTM-REG-03.P1</option>
                            </select>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="small-12 medium-8 medium-offset-2 large-6 large-offset-3 columns">
                    <input type="submit" name="submitLogin" value="Login" class="button expand buttonBlack" />
                </div>
            </div>
        </form>

        <script type="text/javascript" src="../js/vendor/jquery.js"></script>
        <script type="text/javascript" src="../js/foundation.min.js"></script>
        <script type="text/javascript">
            $(document).foundation();
        </script>
    </body>
</html>

这看起来有点像我为我的项目构建的登录系统,就 returning 错误消息而言,您可以将错误分配给变量并与 [=78= 一起使用] 传下去。另一件可能更容易做的事情是使用 ajax 调用登录,而不是直接在页面上使用 php。这也允许您动态分配 error/success 消息。

但是就 return 错误消息而言,您可以将 catch 更改为类似这样的内容

        $status = [];
        if(!empty($selectStudentCheck)) {
            status['status'] = true;
            return status;
        }
        else {
            $status['status'] = false;
            $status['msg'] = "Studentnumber or class is not correct";
            return $status;
        }

这也将消除对 showErrorMessage() 功能的需要。然后,如果要显示错误,您只需检查 ['status'],然后显示 ['msg']。以上也适用于 ajax 调用。

我注意到您可能想要做的另一件事是将您的数据库信息移动到要包含的单独文件中,以便您可以对其设置权限,从而使信息更加安全。我对我所做的事情如下

db_info.inc

<?php
# Defining Database Values to avoid hardcoding in each file.
define ('DB_USER', 'user');
define ('DB_PASS', 'supersecret password');
define ('DB_HOST_WRITE', 'host1'); # Master DB
define ('DB_HOST_READ', 'host2'); # Slave DB
define ('DB_ONE', 'database1');
define ('DB_TWO', 'database2');

然后只需包含文件并将它们分配给您需要的变量并将它们插入到需要的位置。如下图。

class User {

# Set class wide variables
private $db;
public $dbuser = DB_USER;
public $dbhost = DB_HOST_WRITE;
public $dbname = DB_ONE;
public $dbpass = DB_PASS;

您也可以在构造中构造实际的数据库连接。实际登录 class 这样您就不必将其传递到登录函数中。这还可以让您更轻松地为用户分配数据库权限以实现特殊功能。

public function __construct() {
    try {
        $this->db = new PDO("mysql:host=" . $this->dbhost . ";dbname=" . $this->dbname, $this->dbuser, $this->dbpass);
        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch (Exception $ex) {
        file_put_contents($this->pdolog, $ex->getMessage(), FILE_APPEND);
    }
}

希望对您有所帮助

==========

对于 ajax 的调用是我自己实现的片段

登录表单

<form id="formLogin">
    <input class="form-control center-block text-center" name="username" id="username" placeholder="Username" type="text" required>
    <input class="form-control center-block text-center" name="password" id="password" placeholder="Password" type="password" required>
    <input type="button" value="Login" id="login" class="btn btn-block btn-primary center-block" onclick="userlogin(event, '#formLogin')">
</form>

onlick 选项是神奇的部分。它调用以下 jquery 脚本。

function userlogin(event, loginform) {
  event.preventDefault();

  $('#login').fadeOut();

  $.ajax({
        type: 'POST',
        url: '/inc/login.php',
        data: $(loginform).serializeArray(),
        dataType: 'json',
        success: function(data) {
          if (data.status == 'error') {
            alert(data.statusmsg);
            $('#login').fadeIn();
          }
          if (data.status == 'success') {
            window.location = '/account/';
          }
        },
        error: LogonError
  });
}
function LogonError() {
   alert('Error: The system could not log you in.' +
       '\n\nIf you believe this is an error please email the' +
       '\nAdministrator at admin@blacklistlogistics.com');
}

这从表单中获取值 jquery 执行所有额外的 magix,因此我不必将其传递给 php 页面 login.php

login.php

$user = @$_POST['username'];
$pass = @$_POST['password'];

$response = array();

if($user == null) {
    $errors = 1;
    $response['statusmsg'] .= "Please enter your username.\n";
}
if($pass == null) {
    $errors = 1;
    $response['statusmsg'] .= "Please enter your password.\n";
}
if($errors === 1) {
    $response['status'] = 'error';
    echo json_encode($response);
    return;
} else {
    $login = new User;
    $loginstatus = $login->login($user, $pass);

    if($loginstatus === 0) {
        $response['status'] = 'error';
        $response['statusmsg'] = "The system was unable to log you in. Please try again later.\nIf this error presists please inform the site administrator.";
        echo json_encode($response);
        return;
    }
    if($loginstatus === 2) {
        $response['status'] = 'error';
        $response['statusmsg'] = "There was an error. Please try again later.\nIf this error presists please inform the site administrator.";
        echo json_encode($response);
        return;
    }
    if($loginstatus === 1) {
        $response['status'] = 'success';
        echo json_encode($response);
        return;
    }
}

这会获取 jquery 从 post 传递给我们的信息,然后将其传递给登录函数,然后检查 return 值并将所需的信息传递回jquery 显示错误等

登录功能

public function login($username, $password) {
        # Set login time
        $logintime = date('Y-m-d H:i:s');
        $ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP);

        # setting db connection inside try for exception handling
        try {
            $conn = $this->db;

            $stmt = $conn->prepare('SELECT * FROM Members WHERE UserName = :username');
            $stmt->execute(array(':username' => $username));
            $results = $stmt->fetch(PDO::FETCH_ASSOC);
            $stmt = NULL;
        } catch (PDOException $ex) {
            $conn = NULL;
            file_put_contents($this->pdolog, $ex->getMessage(), FILE_APPEND);
            return 2;
        }

        if ($results === FALSE || $results['AccountActive'] === 0) {
            $conn = NULL;
            return 0;
        } else {
            if (password_verify($password, $results['UserPass'])) {
                try {
                    $stmt = $conn->prepare('UPDATE Members SET LastDate = :lastdate, LastIP = :lastip, FailCount = :failcount WHERE MemberID = :memberid');
                    $stmt->execute(array(':lastdate' => $logintime, ':lastip' => $ip, ':failcount' => 0, ':memberid' => $results['MemberID']));
                } catch (PDOException $ex) {
                    $conn = NULL;
                    file_put_contents($this->pdolog, $ex->getMessage(), FILE_APPEND);
                    return 2;
                }

                $conn = NULL;
                $_SESSION['login'] = 1;
                $_SESSION['MemberID'] = $results['MemberID'];
                $_SESSION['UserName'] = $results['UserName'];
                return 1;

            } else {
                $conn = NULL;
                return 0;
            }

        }

    }

函数有运行并且数据传回jquery调用后,jquery然后处理success或[=23=中的数据]份。

希望这也有帮助,也很抱歉 copy/paste 代码太长了。我还完整地保留了我的代码的大部分额外部分,以防你想从中汲取灵感。