Zend框架:模型,映射器; 映射器中的默认字段和模型中的字段操作?

Ste*_*ths 5 orm zend-framework model datamapper

我在Zend Framework中创建一个简单的ORM,使用DbTable/Mapper/Model方法粗略地封装公共库应用程序.我不确定我在做与用户相关的类的方式是否正确,因为我有一些逻辑Mapper_User,有些在Model_User.

Mapper_User

<?php
class Mapper_Users {

/*
createModelObject would be called by a Controller handling a Form_Regsiter's
data, to create a new Model_User object. This object'd then be saved by the
same Controller by calling Mapper_Users->save();
*/
    public function createModelObject(array $fields) {
        if(!isset($fields['date_registered']))
            $fields['date_registered'] = date('Y-m-d H:i:s');
        if(!isset($fields['max_concurrent_rentals']))
            $fields['max_concurrent_rentals'] = 3;
        return new Model_User($fields);
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

Model_User从头开始创建新对象的方法中(例如,不是从DB中提取记录,而是注册新用户),我Model_User使用Form提供的名称/用户名/密码实例化一个新的,然后设置一些对象属性例如注册日期,"一次允许的最大书籍"等.这些数据被填入Model_User其中Mapper_User,然后在Mapper_User->save();被调用时写入数据库.Mapper感觉就像是正确的地方 - 保持模型轻盈.

这是正确的,还是应该将默认字段设置在Model_User其内部?

Model_User

<?php
class Model_User {

    public function setPassword($value) {
        $this->password = md5($value);
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

在设置用户对象的密码时,我正在Model_User->setPassword($value);按照您的预期执行$this->password = md5($value);此操作,并在此方法中执行此操作.再一次,这感觉是正确的 - 尝试在Mapper_User->save();方法中执行md5步骤会导致问题,如果Model_User从数据库中取出一个,因为密码字段显然已经被散列.

这就是我的困惑所在.在我看来,所有与"与用户相关的字段"的逻辑应该存在于它的模型或Mapper中,但是在这里我在Mapper中有一些逻辑(默认字段),而在一些(字段操作)中模型.这是正确的,还是应该尝试以某种方式获取模型中的默认字段或Mapper中的字段操作?

感谢您抽时间阅读!


编辑@RockyFord:

Mapper_User 实际上扩展了我写的一篇摘要,因为我不喜欢在500个Mapper_*.php文件中编写相同的基本代码,因此有一些官僚作风,但它的有效 __construct()非常简单:

<?php
class Mapper_Users {

    public function __construct() {
        $this->_db = new DbTable_Users();
        if(!$this->_db instanceof Zend_Db_Table_Abstract)
            throw new Exception('Invalid table data gateway provided');
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

Roc*_*ord 1

这可能需要一段时间才能完全回答,但我将从问题开始setPassword

您当前的:

public function setPassword($value) {
        $this->password = md5($value);
    }
Run Code Online (Sandbox Code Playgroud)

现在这与惯例或最佳实践无关,而是实用性。

问你自己:

当您检索用户对象的数据库记录并且该数据库记录包含哈希密码时会发生什么?

答案:当您构造用户对象并调用$this->setPassword($password);或等效方法时,您将应用哈希值到哈希值。

因此,您几乎有义务在映射器的 save() 方法或用于更新密码的方法中对密码进行哈希处理。将数据库表中的哈希值视为密码,并将输入到表单字段中的值视为该密码的占位符。

下一部分:

在我看来,与“与用户相关的字段”相关的所有逻辑都应该存在于其模型或映射器中

这基本上是正确的。

属于对象域 (Model_User) 的所有内容均应在域模型类 (Model_User) 中寻址。

映射器仅将数据对象(数据库行、json 字符串、xml 文件、平面文件、csv 文件... )转换(映射)为可以实例化域对象 (Model_User) 的形式。

因此,您最终可能会为给定的域对象提供多个可用的映射器,或者一个映射器可能映射到多个数据源。

如果您不再将数据视为“字段”(这可能会让您的头脑一直停留在数据库中),而是根据属性特征来考虑对象,这可能会对您有所帮助。

因为当你深入到最基本的层面时,Model_User对象就是:

class Model_User {
    protected $id;
    protected $name;
    protected $password;
    //continue....
}
Run Code Online (Sandbox Code Playgroud)

所有的 getter、setter、构造函数和其他方法都差不多,因此我们可以将值放入这些变量中。