我想创建一个App
对象,其中包含我的数据库,清理程序和用户的对象。这样,我可以简单地使用单个App对象,而不是单独调用所有这些不同的对象,因为我的大多数其他对象将需要大多数(如果不是全部)这些对象用于其中的方法。
User
对象将来会有CRUD方法,因此可以更改其属性,因此,我不想要包含CRUD方法的单独对象和处理用户身份验证的对象,原因是我不希望在两个单独的类中具有完全相同的对象属性,因为技术上完全相同的对象。
那就是说,这种递归发生有多糟糕(请参阅App
类中如何使用User
对象)?我是否应该采取措施对此进行不同的编码?这是一个大问题吗?请记住,将为CRUD方法调用此User
类,因此登录的用户只需使用不同的变量名称并实例化其新实例,就可以通过此对象更改任何其他用户
class App {
public $db;
public $sanitizer;
public $user;
public $settings;
function __construct () {
// create $app->db object
$db = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->db = $db;
// create $app->sanitizer object
$this->sanitizer = new Sanitizer();
// set $app->settings
$this->setSettings();
// create $app->user object
$this->user = new User($this); // NOTE THE RECURSION HERE
$this->user->setIsSignedIn();
if ($this->user->is_signed_in) {
$this->user->populateById();
}
}
function setSettings () {
$sql = 'select * from `settings`';
$stm = $this->db->prepare($sql);
$stm->execute();
$res = $stm->fetchAll();
if ($res) {
$res = $this->sanitizer->action('sanitize', $res);
foreach ($res as $r) {
$this->settings[$r['key']] = $r['value'];
}
}
}
}
class User {
public $app;
public $id;
public $username;
public $password;
public $token;
public $is_signed_in = false;
function __construct ($app) {
$this->app = $app; // AGAIN, *RECURSION*
}
function populateByPost () {
foreach ($_POST as $k => $v) {
if (property_exists($this, $k)) {
$this->$k = $v;
}
}
}
function populateById () {
$sql = 'select * from `users` where `id`=:id';
$stm = $this->app->db->prepare($sql);
$stm->bindParam(':id', $this->id);
$stm->execute();
$res = $stm->fetch();
if ($res) {
$res = $this->app->sanitizer->action('sanitize', $res);
foreach ($res as $k => $v) {
$this->$k = $v;
}
}
}
function credentialsValid () {
$sql = 'select * from `users` where `username`=:username';
$stm = $this->app->db->prepare($sql);
$stm->bindParam(':username', $this->username);
$stm->execute();
$res = $stm->fetch();
if ($res) {
if (password_verify($this->password, $res['password'])) {
$this->id = $res['id'];
return true;
}
}
return false;
}
function createToken () {
$this->token = password_hash($this->id.'|'.$this->username.'|'.$this->password, PASSWORD_DEFAULT);
$sql = 'insert into `user_tokens` (`id_user`, `token`) values (:id_user, :token)';
$stm = $this->app->db->prepare($sql);
$stm->bindParam(':id_user', $this->id);
$stm->bindParam(':token', $this->token);
$stm->execute();
}
function setSessionVars () {
$_SESSION['id_user'] = $this->id;
$_SESSION['token'] = $this->token;
if (isset($_POST['remember_me'])) {
setcookie('id_user', $this->id, time() + 31556926, '/');
setcookie('token', $this->token, time() + 31556926, '/');
}
}
function setIsSignedIn () {
if (isset($_COOKIE['id_user'])) {
$id_user = $_COOKIE['id_user'];
$token = $_COOKIE['token'];
}
else if (isset($_SESSION['id_user'])) {
$id_user = $_SESSION['id_user'];
$token = $_SESSION['token'];
}
if (isset($id_user)) {
$sql = 'select * from `user_tokens` where `id_user`=:id_user and `token`=:token';
$stm = $this->app->db->prepare($sql);
$stm->bindParam(':id_user', $id_user);
$stm->bindParam(':token', $token);
$stm->execute();
$res = $stm->fetch();
if ($res) {
$this->id = $res['id_user'];
$this->is_signed_in = true;
}
}
}
function signOut () {
$_SESSION['id_user'] = '';
$_SESSION['token'] = '';
session_destroy();
if (isset($_COOKIE['id_user'])) {
setcookie('id_user', '', time() - 1, '/');
setcookie('token', '', time() - 1, '/');
}
}
// CRUD METHODS TO BE ADDED HERE LATER
}
显然,当我print_r App
对象时,它告诉我由于App->user
构造中的代码,App
对象中存在递归。
同样,我只是好奇,如果这是一个非常糟糕的事情,我绝对应该重新编码。任何见解将不胜感激。