2008年6月17日 星期二

Zend_Acl_Resource的樹狀結構



Zend_Acl_Resource的樹狀結構

要建立Zend_Acl_Resource的樹狀結構,對我來說難度滿高的,想了很久,都想不出解法,最後看了陳瑩光老師寫的新版學務系統中的認證模組,找到了解法,不過雖然解法找到了,卻不明瞭為何要這樣寫,思考了很久,才把需要了解的區塊,一個個弄清楚,再把整個解法背後運用的思考邏輯用freemind全部畫出來,再依照這張畫出來的圖,自己弄出一個建構Zend_Acl_Resource樹狀結構的原型,我自己寫的程式改良了原來程式碼的部份寫法,不過,沒有將錯誤機制考慮在內,也就是說,在資料庫內的資料都必須是正確的。



建立Zend_Acl_Resource樹狀結構的資料庫內的欄位資料

資料表:resource

欄位
id----------Primary key(resource的名稱)
parent_id---參照id或是null


要建立Zend_Acl_Resource的樹狀結構的第一步就是將資料從資料庫中抓到陣列中,如果不這麼做,那麼每建立一層樹狀結構就要把資料表的全部資料讀取一遍,是非常耗時的,如果把資料抓到陣列中,由於陣列是存放在記憶體中,比起存放在資料表中的資料,讀取速度快非常多,為了效能的考量,一定要先將資料讀入陣列中。

第二步就是開始建立整個樹狀結構,原理是利用迴圈的方式,第一次迴圈會找出所有id未註冊且parent_id是null的陣列值,註冊為最上層的resource,第二次迴圈會找出所有id未註冊且parent_id(參照到最上層resource的id)已註冊的陣列值,註冊為第二層的resource,第三次迴圈會找出所有id未註冊且parent_id(參照到第二層的resource的id)已註冊的陣列值,註冊為第三層的resource。這個迴圈會一直持續到所有id都註冊為止。


Zend_Loader::loadClass('Zend_Acl');
Zend_Loader::loadClass('Zend_Acl_Role');
Zend_Loader::loadClass('Zend_Acl_Resource');
Zend_Loader::loadClass('Zend_Db');
Zend_Loader::loadClass('Zend_Config');
Zend_Loader::loadClass('Zend_Registry');

$baseDir=Zend_Registry::get('baseDir');

$config=new Zend_Config(require($baseDir.'/application/etc/db.php'));

/**
* 讀取資料表欄位,將資料表內的資料讀入陣列
*/
$db=Zend_Db::factory($config->public);
$db->query('set names utf8');
$sql='select id,parent_id from resource';
$stmt=$db->query($sql);
$rows=$stmt->fetchAll();




/**
* 建立resource的樹狀結構
*/
$acl=new Zend_Acl();
do{
$flag=false;
foreach($rows as $row){

/**
* 建立resource樹狀結構的判斷流程程式碼
*/
if(!$acl->has($row['id']) && ($row['parent_id']===null || $acl->has($row['parent_id']) ) ){
$acl->add(new Zend_Acl_Resource($row['id']),$row['parent_id']);
}

/**
* 判斷所有id是否已註冊為resource,如果有未註冊的id,旗標設為true,繼續執行迴圈
* 如果所有的id都已註冊,就會跳出迴圈
*/
if(!$acl->has($row['id']))
$flag=true;

}
}while($flag);

沒有留言: