在阅读了 Matthew Weier O'Phinney 的许多关于在模型中实施 ACL 的文章后,我一直专注于实现这一目标的最佳方法。然而,在进一步研究领域对象的最佳实践后,我了解到这些模型不应包含对数据映射器或任何 CRUD 操作的任何引用。
以 ERM 软件为例,它根据销售和采购订单维护库存并处理进出公司的货物。我想象有几个域......
- 公司
- 运输
- 命令
- 产品
- 集会
- 还有其他几个
由于公司可以有不同的类型(例如制造商、供应商、零售商),因此此信息存储在我的数据库中的许多表中(例如公司、类型、公司类型)。因此,我的公司域有一个数据映射器,它使用每个数据库表的 Zend_Db_Table 实例的对象。
在我的控制器操作中,我知道应该很少有逻辑。例如,创建一个新公司可能会像这样......
public function createAction()
{
// Receive JSON request from front end
$data = Zend_Json::decode($request);
$companyObj = new App_Model_Company();
$companyObj->populate($data);
$companyMapper = new App_Model_DataMapper_Company();
$companyMapper->save($companyObj);
}
考虑到这一点,我觉得最好将我的 ACL 检查合并到 DataMapper 中,并将验证合并到域对象中。My Domain 对象都扩展了一个基础抽象类,它重载了 PHP 的魔力__set
和__get
方法。在每个域对象的构造函数中,我通过$_properties
使用键填充数组来定义对象的属性。这样,我的__set
方法看起来像......
public function __set($property, $value)
{
$className = __CLASS__;
if(!array_key_exists($property, $this->_properties))
{
throw new Zend_Exception("Class [ $className ] has no property [ $property ]");
}
// @return Zend_Form
$validator = $this->getValidator();
/*
* Validate provided $value against Zend_Form element $property
*/
$this->properties[$property] = $value;
}
}
我所有的数据映射器的save()
方法 typehint App_Model_DomainObjectAbstract $obj
。
问题 #1 - 由于我的数据映射器将处理所有 CRUD 操作,并且域对象实际上应该只包含特定于该域的属性,我觉得 ACL 检查属于数据映射器 - 这可以接受吗?
我试图避免在我的控制器中实例化数据映射器,但这似乎不合理,因为我认为我对这种设计模式有了更好的理解。
问题 #2 - 我是否过于复杂了这个过程,我是否应该编写一个 ACL 插件来Zend_Controller_Plugin_Abstract
根据方法中的传入请求扩展和处理 ACL preDispatch()
?
非常感谢您的宝贵时间!