在 PHP 開發中,遞歸是處理樹狀結構數據(如角色權限、分類目錄、組織架構)的核心技術。本文通過三個實際業務場景,詳細演示如何利用遞歸函數高效解決角色體系中的層級關係問題。
當需要將某角色及其所有下級角色的 ID 拼接為字符串(例如用於 SQL 查詢的 IN 條件)時,可使用以下遞歸函數:
// 遞歸獲得角色ID字符串
function explodeRole($roleObj, &$resultStr) {
if (0 < count($roleObj->childRoleObjArr)) {
foreach ($roleObj->childRoleObjArr as $childRoleObj) {
if ('' == $resultStr) {
$resultStr .= "{$childRoleObj->id}";
} else {
$resultStr .= ", {$childRoleObj->id}";
}
explodeRole($childRoleObj, $resultStr);
}
}
}
關鍵點解析:
&$resultStr 避免多次字符串拷貝,提升性能childRoleObjArr 為空時自動終止遞歸將扁平的角色數據轉換為包含子角色的樹狀結構,便於前端樹形組件渲染:
// 遞歸獲取級聯角色信息數組
function makeRoleRelation(&$roleObjArr) {
foreach ($roleObjArr as $item) {
$item->childRoleObjArr = getRoleObjArrByParentId($item->id);
if (0 < count($item->childRoleObjArr)) {
makeRoleRelation($item->childRoleObjArr);
}
}
}
設計優勢:
數據層封裝,通過父角色 ID 查詢直接子角色:
// 通過父角色的id獲取子角色信息
function getRoleObjArrByParentId($parentid) {
$operCOGPSTRTSysRole = new COGPSTRTSysRole();
$operCOGPSTRTSysRole->setColumn($operCOGPSTRTSysRole->getAllColumn());
$operCOGPSTRTSysRole->setWhere("parentroleid={$parentid}");
$roleObjArr = $operCOGPSTRTSysRole->convResult2ObjArr($operCOGPSTRTSysRole->selectTable());
return isset($roleObjArr) ? $roleObjArr : array();
}
最佳實踐建議:
對於角色權限這類通常不超過 10 層、節點數百級的場景,遞歸代碼可讀性遠優於迭代,性能差異可忽略。但若處理萬級節點的文件系統掃描,建議改用基於堆棧的非遞歸實現。
這三個遞歸函數構成了角色權限管理的核心工具集:getRoleObjArrByParentId 負責數據獲取,makeRoleRelation 負責結構組裝,explodeRole 負責業務提取。掌握這種「查-構-用」的遞歸模式,可輕松應對各類樹狀結構業務。