在閱讀Matthew Weier O'Phinney關於在模型中實現ACL的許多帖子後,我一直專注於做這件事的最佳方式。但是,在進一步研究域對象的最佳實踐後,我明白這些模型不應包含對數據映射器或任何CRUD操作的任何引用。在哪裏實施Zend_ACL與域對象和數據映射器?
以ERM軟件爲例,該軟件可以根據銷售和採購訂單維護庫存並處理來往於公司的貨物。我想有幾個域...
- 公司
- 出貨
- 訂購
- 產品
- 大會
- 和其他幾個人
由於公司可以有不同類型(例如製造商,供應商,零售商),這些信息存儲在許多表格中跨越我的數據庫(例如公司,類型,company_types)。因此,我有一個公司域的數據映射器,它使用對象作爲每個數據庫表的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和驗證到域對象。我的域對象全部擴展了基本的抽象類,它重載了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 - 我是在這個過程複雜,我應該代替編寫基於preDispatch()
方法傳入的請求延長Zend_Controller_Plugin_Abstract
和處理ACL訪問控制列表插件?
非常感謝您的時間!
+1供參考@tereskos解釋。 – Jojo
+1感謝您的參考!這對我來說很有意義。我目前的ACL類處理從數據庫中建立'resources','roles'和'privileges' - 這一切都很好。我看到我可以用@teresko提出的Decorator模式來實現這個功能。但是,我對於如何實現這種模式作爲插件略有困惑。我明白,在'preDispatch'方法中,我可以輕鬆地爲當前的Zend_Auth實例構建一個ACL對象,但我對如何基於傳入請求中包含的數據構建域對象感到困惑(JSON,來自ExtJS) 。 –
@JohnHall讓我知道更新的答案是否有幫助。 –