我想看到一个系统的理想框架,该系统具有一组对象(即用户),其中数据包含在数据库中。有人建议我有一个User类和一个UserMapper类,这是我对它应该是什么样子的理解:
用户.class.php
/* The class for constructing any user's information
*/
class User {
protected $userId, $email, $userGroup;
protected function getEmail() {
return $this->email;
}
protected function getUserId() {
return $this->userId;
}
public function __construct($userId, $email, $userGroup) {
$this->userId = $userId;
$this->email = $email;
$this->userGroup = $userGroup;
}
}
class UserMapper {
// database connection
private $db;
public function __construct($db)
{
$this->db = $db;
}
public function findByUserId ($userId) {
$userObject = new User();
$q = $this->db->prepare("SELECT userId, email, userGroup FROM user WHERE userId = :userId");
$q->bindValue(":userId", $id);
$q->setFetchMode( PDO::FETCH_INTO, $userObject);
$q->execute();
$q->fetch(PDO::FETCH_INTO);
return $userObject;
}
}
?>
主.php
<?php
include user.class.php;
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
$getUser = new UserMapper($dbh);
$user = $getUser->findByUserId(41);
echo $user->getEmail();
?>
但就主要方面而言.php这似乎有点混乱。我不能创建一个PDO对象并在所有脚本中定义它吗?以及用户映射器对象?或者每次我想从数据库中获取用户时,我都需要创建一个新的userMapper对象,然后找到ByUserId(如上所述)。或者有更简单的方法可以做到这一点吗?
如果我想在类 User 中调用用户组对象,我将如何执行此操作?(这也需要通过PDO连接到数据库)。执行以下操作似乎很混乱:
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
$getUserGroup = new UserGroupMapper($dbh);
$userGroup = $getUserGroupMapper->findByUserId($this->userGroup);
?>
我能想到的一件事是使这个类成为一个单例,并在类的声明之上创建$user,所以每当你包含这个类时,你都会有那个用户对象。
我不能制作一个 PDO 对象并在我的所有对象中定义它吗 脚本?以及用户映射器对象?
您实际上正在寻找前端控制器。
也就是说,为了避免相同类的相同实例化,您应该准备它们。大多数人通常在bootstrap.php
中执行此操作,"调整"所有必需的依赖项。
但前端控制器实现还包括调度程序和路由器。我不会深入探讨这个问题,而是专注于你试图解决的问题。
工厂模式
它基本上抽象了实例化逻辑。好处是:1)你可以延迟对象实例化2)你可以避免全局状态,这对单元测试不利。它的简化版本如下所示:
class UserFactory
{
private $pdo;
private $cache = array();
public function __construct($pdo)
{
$this->pdo = $pdo;
}
public function build($mapper)
{
if (isset($this->cache[$mapper])) {
return $this->cache[$mapper];
} else {
// Inject an instance into a mapper
$instance = new $mapper($this->pdo);
// Save the state into a cache
$this->cache[get_class($instance)] = $instance;
return $instance;
}
}
}
最后
一个非常简化的引导程序版本看起来像这样,
<?php
/* File : bootstrap.php */
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
// Include here UserFactory class
$userFactory = new UserFactory($dbh);
// Its kinda ready to be used
您只需包含在需要访问用户的所有脚本中
<?php
/* File: main.php */
include(__DIR__ . '/bootstrap.php');
$getUser = $userFactory->build('UserMapper');
$user = $getUser->findByUserId(41);
echo $user->getEmail();
您需要改用FETCH_CLASS,并且不需要userMapper,只需扩展PDO即可,然后在一个类中设置正确的获取模式。
不要忘记使类定义可用或使用自动加载器
$this->statement->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE,"className");
FETCH_PROPS_LATE是为了让构造函数首先在你的类中被触发,但是在你的情况下你不需要构造函数,所以只是失去它。如果你决定保留它,你应该先看看这里。
希望这有助于好运