最佳实践:表示单个数据库表的类

时间:2017-08-22 17:03:32

标签: php oop

我有一个用户数据库表,其中包含以下字段:id,username,password,email,roles,password password token和expiration等。

现在我需要一个类来读写用户数据。

为每个数据库字段创建类变量以及从/向它们读取/写入是否更好:

class User {
    private $db;
    private $user_id;
    private $username;
    private $email;

    [...]

    public function getUsername() {
        return $this->username;
    }

    public function setUsername($name) {
        $this->username = $name;
    }

    public function readDB() {
         $sth = $this->db->query("SELECT * FROM users WHERE id = ?", 
         array((int)$this->user_id));
         $user = $sth->fetch();
         if($user !== false && is_array($user)) {
             $this->username = $user['username'];
             $this->email = $user['email'];
             [...]
    }

    public function writeDB() {
        [...]
        $this->db->insert('users', array(
            'username' => $this->username
            'email' => $this->email), array('user_id' => $this->user_id)); 
    }
}

或者没有类变量,并按照这样做:

class User {
    private $db;

    [...]

    public function readDB($userID) {
         $sth = $this->db->query("SELECT * FROM users WHERE id = ?", 
         array((int)$userID));
         $user = $sth->fetch();
         return $user;
    }

    public function writeDB($userID, $username, $email ...) {
        $this->db->insert('users', array(
            'username' => $username
            'email' => $email), array('user_id' => $userID)); 
    }
}

我没有看到第一个解决方案的优点,除了以后很容易更改数据库字段名称,但这可以通过较低的readDB版本中的简单更改轻松完成。

第一个版本的缺点是,我需要编写大量的get和set方法,方法调用需要更多的处理时间,我必须首先检查每个类变量,是否已经设置过插入/更新数据。如果缺少参数,第二个版本将自动产生方法参数错误。

有时我只需要用户的电子邮件地址,第一个版本总是需要首先读取数据库中的所有字段,然后调用getEmail方法。第二种方法允许编写一个返回单个数据库字段的特殊方法(SELECT email FROM user WHERE user_id =?)。这会减少数据库负载。

您更喜欢哪种方式?为什么?

1 个答案:

答案 0 :(得分:1)

您应该将域实体逻辑与持久性逻辑分开。没有一个包含所有内容的类,因为那样你最终会得到active record反模式的美化版本。

更好的选择是让domain object处理业务逻辑(例如验证和数据转换),并将存储逻辑保留在单独的data mapper实例中。

在实践中,代码看起来有点像这样:

$user = new Entity\User;
$user->setUsername('Drunk Lizard');

$mapper = new Mapper\User($pdo);
$mapper->fetch($user);

if (!$user->hasStatus(Entity\User::UNVERIFIED)) {
    throw new InvalidAction;
}

if (!$user->hasToken($request->get('token'))) {
    throw new WrongToken;
}

$user->setStatus(Entity\User::VERIFIED);
$mapper->store($user);