PHP - 保留整个目录中类的实例化

时间:2016-04-12 13:08:48

标签: php sql class

我正在构建一个小应用程序,因为我学习了PhP和SQL。现在,我不得不保留我的一个类的实例化,而不必在每次页面加载时都保持实例化。我有两个表UsersRepresentatives。登录功能找出他们的表并将其登录,然后创建该类的新实例。当构造该类时,它会执行一些操作并将它们重定向到适当的模块。似乎我能够实例化该类,但是第二次我改为新文件,$current_user变为空。我不想继续恢复它,因为最终在__construct()上我想将一些用户信息存储为私有变量,所以我只想设置一次$current_user并在整个项目中使用它。再一次,对此有点新意,所以我希望我措辞正确。现在我只是建立了Administrator类(但是当我解决这个问题时,我现在只为该表构建)。这是我的类和登录功能所在的位置(此文件在我的所有页面上都是require_once())。

require_once('functions.php');
// Define Database Constants
define("DB_SERVER", "localhost");
define("DB_USER", "root");
define("DB_PASS", "root");
define("DB_NAME", "livelab");
if(empty($current_user)){
  $current_user;
}
function login_user($username, $password){
  global $current_user;
  $connection = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
  $sql="SELECT 'Users' AS tableName, userId as id, username as username, password as password FROM Users WHERE username='{$username}' UNION SELECT 'Representatives' as tableName, repId as id, username as username, password as password FROM Representatives WHERE username='{$username}'";
  $result = mysqli_query($connection, $sql);
  $user = mysqli_fetch_array($result);
  if(!$user){
    header('Location:' . './index.php');
  }else{
    if($password == $user["password"]){
      mysqli_close($connection);
      switch($user["tableName"]) {
        case 'Users':
          $current_user = new Administrator();
          break;
        case 'Representatives':
          $current_user = new Representative();
          break;
      }
    }
  }
}

class Administrator{
  private $connection;
  private $user_table = 'Users';
  private $user_id = 2; // I have this as a set value for test purposes right now
  private $module = './mod-administrator/';
  private $current_cookie;

 //public vars
 public $test = "hello world";

  function __construct(){
    $this->open_connection();
    if(!session_id()) : session_start(); endif;
    $this->current_cookie = mysqli_real_escape_string($this->connection, hash_password(uniqid()));
    setcookie('login_token', $this->current_cookie, time() + 60, "/");
    mysqli_query($this->connection, "UPDATE " . $this->user_table . " SET cookieHash='" . $this->current_cookie . "' WHERE userId='" . $this->user_id . "'");
    header('Location:' . $this->module);
  }
  // The function that opens our connection to our DB
   private function open_connection(){
    $this->connection = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
    if(mysqli_connect_errno()){
      die("Database connection failed: " . mysqli_connect_error() . " ( " . mysqli_connect_errno()  . " ) ");
    }
  }
}

2 个答案:

答案 0 :(得分:2)

  

基本概述:您目前正在使用更加程序化的编程方法来降低软件移动数据的能力。我建议对这个项目采用更加面向对象的方法,首先设计代表用户的东西。

数据库层次结构:

Users
    - User_Id (int) Primary Key
    - Username (varchar) Primary Key
    - Salt (varchar) Primary Key
    - Password (varchar)
    - Login_Key (varchar) Primary Key
    - Group_Id (int)
    - Ect...

Usergroups
    - Group_Id (int) Primary Key
    - Admin_Access (bool)
    - Ect...

计划层次结构:

Object
    - Database
    - User
    - Group Enumeration

您的基础架构示例:

class User
{
    public $Username;
    public $Email;
    public $Group;
    public function __construct($u,$e,$g = "Registered")
    {
        $this->Group = (new UserEnum($g))->GetValue();
        $this->Email = $e;
        $this->Username = $u;
    }
    public function GenerateUser()
    {
        // Connect to the Database
        // See if the user exist
        // Handle it and upload the user
    }
}

class UserEnum
{
    public function __construct($c)
    {
         private $Value;
         switch ( $c )
         {
             case "Admin": $this->Value = 1; break;
             case "Moderator": $this->Value = 2; break;
             default: $this->Value = 3; break;
         }
    }
    public function GetValue() { return $this->Value; }
}

用法可能类似于:

(new User($_POST['name'],$_POST['email'],$_POST['group']))->GenerateUser();
  

对项目采用更多OOP方法,您可以在整个项目中使用相同的数据,而无需defineglobal。以一个人为例,每个人都有一个名字。在Object中,您可以通过为其指定属性来指定Object需要具有名称,然后将Object作为Person使用。即:$People = array(new Person('Bob'), new Person('Jimmy')); - 这允许更动态的方法,您可以通过构造函数方法传递名称,并轻松地向该人添加更多属性,而无需编辑大量代码。

编辑:我建议您添加某种软件初始化,以确定用户是否已登录,例如:

// TODO: Create a Settings Object and Controls Object
session_start();
if ( !isset ( $_SESSION[$Settings->CookieName] ) ):
    $Settings->UserControls->CanPost = false;
    // Ect...
endif;

编辑:另请注意,您的目录设置很重要,应该在每个页面上以相同的方式加载该状态,即使用每个文件中的上述初始化文件。

答案 1 :(得分:1)

要保留对象的状态或任何变量,您需要将其保存在$_SESSION数组中。您存储在其中的值将在整个会话中可用,直到用户注销或会话超时。

session_start();
$_SESSION['current_user'] = serialize($current_user);

您可能已经注意到serialize。要在会话中存储对象,需要对它们进行序列化,因为它们是复杂的数据结构而不是原始值。

要访问对象的先前状态,您需要执行相反的操作:

session_start();
$current_user = unserialize($_SESSION['current_user']);

我建议在PHP文档中阅读有关sessions的一些信息。