我正在Zend中创建一个简单的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);
}
}
?>在从零开始创建新的Model_User对象的方法(例如,不是从DB中提取记录,而是注册一个新用户)中,我实例化了一个新的Model_User,使用表单提供的名称/用户名/密码,然后设置一些对象属性,比如注册日期、“一次性允许的最大图书”等等。这些数据被Mapper_User填充在Mapper_User中,然后在调用Mapper_User->save();时写入DB。Mapper觉得这是合适的去处-保持模型灯。
这是正确的,还是应该在Model_User本身内设置这样的默认字段?
Model_User
<?php
class Model_User {
public function setPassword($value) {
$this->password = md5($value);
}
}
?>当设置用户对象的密码时,正如您可能预期的那样,我在Model_User->setPassword($value);中执行此操作,并在此方法中执行$this->password = md5($value);操作。同样,这也是正确的--尝试在Mapper_User->save();方法中执行Mapper_User->save();步骤会导致问题,如果从DB中提取Model_User,因为密码字段显然已经被散列。
这就是我困惑的地方。在我看来,与“与用户有关的字段”相关的所有逻辑要么位于它的Model中,要么位于它的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');
}
}
?>发布于 2012-09-09 15:25:09
这可能需要一段时间才能完全回答,但我将从setPassword问题开始。
你现在:
public function setPassword($value) {
$this->password = md5($value);
}现在,这与惯例或最佳做法无关,而是与实用性有关。
问问自己:
当您为用户对象检索数据库记录并且该数据库记录包含哈希密码时会发生什么?
答案:当您构造用户对象并调用$this->setPassword($password);或等效时,您将将哈希应用于哈希。
因此,您几乎有义务在mapper的save()方法或用于更新密码的方法中散列密码。将数据库表中的哈希值视为密码,而在表单字段中键入的值作为该密码的占位符。
下一部分:
在我看来,与“与用户有关的字段”相关的所有逻辑要么位于其模型中,要么存在于其Mapper中。
这基本上是正确的。
属于对象域(Model_User) 的所有内容都应该在域模型类(Model_User)中寻址。
映射器仅用于转换(映射)数据对象(数据库行、json字符串、xml文件、平面文件、csv文件.)可以实例化域对象(Model_User)的窗体。
因此,最终可能会有一个以上的映射器可用于给定的域对象,或者一个映射器可能映射到一个以上的数据源。
如果您停止将数据视为“字段”,这可能会对您有所帮助,因为“字段”可能会将您的头脑保存在数据库中,而是从属性或特性的角度来考虑您的对象。
因为当您深入到最基本的级别时,Model_User对象就是:
class Model_User {
protected $id;
protected $name;
protected $password;
//continue....
}所有的getter、setter、constructors和其他方法都是很好的,所以我们可以将值放入这些变量中。
发布于 2012-09-09 15:28:58
DataMapper负责使用其数据填充对象,并将其持久化。在调用$user->save()时,您似乎是在混合操作,因为您将持久化逻辑放入域对象中。当您使用ActiveRecord模式而不是DataMappers时,这是一种常见的方法,这是一件坏事。
您的DataMapper应该负责保存对象$mapper->save($user);,它只需要更新已更改的属性。因此,只有在设置新哈希时才会更新密码。
更新:
你说过:
..。尝试在md5方法中执行
Mapper_User->save();步骤会导致问题,如果从DB中提取Model_User,因为密码字段显然已经被散列。
创建一个名为setPasswordHash()的方法,并在从数据库中提取时使用它。
记住:别找东西!
与其在映射器中查找数据库,不如请求它。
public __construct(Zend_Db_Table $dbTable) {
$this->dbTable = $dbTable;
}这都是依赖注入的问题。
https://stackoverflow.com/questions/12339665
复制相似问题