2010-02-28 2 views
2

나는 나의 DB에서 부모의 모든 자식의 ID를 얻는 함수를 가지고있다. 그래서 ID 7을 찾으면 5, 6, 10으로 배열을 반환 할 수 있습니다. 그 때 내가하고 싶은 것은 반환 된 ID의 자식을 반복적으로 찾아 아이들의 최종 깊이까지 찾는 것입니다.PHP : 재귀 적으로 부모의 자식을 얻는다.

이 작업을 수행하는 함수를 작성하려고했지만 재귀에 대해 혼란스러워지고 있습니다.

function getChildren($parent_id) { 
    $tree = Array(); 
    $tree_string; 
    if (!empty($parent_id)) { 
     // getOneLevel() returns a one-dimentional array of child ids 
     $tree = $this->getOneLevel($parent_id); 
     foreach ($tree as $key => $val) { 
      $ids = $this->getChildren($val); 
      array_push($tree, $ids); 
      //$tree[] = $this->getChildren($val); 
      $tree_string .= implode(',', $tree); 
     } 

     return $tree_string; 
    } else { 
     return $tree; 
    } 

}//end getChildren() 

함수가 실행 된 후에 발견 된 모든 자식 ID의 1 차원 배열을 반환하고 싶습니다.

답변

3

중첩 된 세트 모델 대신 인접성 (adjacency) 목록 모델


난 당신이 NSM 대신 ALM에서 데이터베이스에 노드를 저장하는 것이 좋습니다 수 있습니까?

어린이 노드를 가져 오는 ALM은 가능한 일이지만 추가 작업이 필요합니다. 자식 노드 또는 모든 노드를 선택하는 중첩 세트 모델을 사용하거나 모든 노드의 깊이를 찾는 경우에도 단일 SQL 쿼리로 수행 할 수 있습니다.

당신이 당신의 문제를 어떻게 풀어 낼 수 있었는지에 대한 빛을 밝히기를 바랍니다. 만약 당신이 아직 프로젝트 전환을 진행하고 있지 않다면 나중에 많은 두통을 줄일 수있을 것입니다. 나를 위해

+0

인접 목록 모델을 사용하면 부모 업데이트/이동이 용이합니까? –

+0

아니요, ALM 테이블을 업데이트하는 데는 몇 가지 쿼리가 필요합니다. 약 6 ~ 귀하의 쿼리를 얼마나 잘 최적화 할 수 있습니다. 선택시 혜택은 모두 이루어집니다. 그런 다음 깊이, 어린이, 부모 등을 얻기 위해 4 개의 쿼리를 선택하는 대신 하나의 쿼리 만 수행하면됩니다. 따라서 삽입 및 업데이트 이상의 항목을 선택하면 ALM imho를 사용해야합니다. – Layke

+0

그 반대편에 있지 않습니까? 중첩 된 세트를 사용하면 각 노드와 연관된 왼쪽 값을 선택하고 정렬하여 전체 트리 (또는 트리의 모든 하위 세트)를 쉽게 검색 할 수 있습니다. 자세한 내용은 http://dev.mysql.com/tech-resources/articles/hierarchical-data.html을 참조하십시오 (MySQL과 관련이 있지만 필요할 경우 다른 RDBMS로 쉽게 이식 할 수 있어야 함). – wimvds

5

이 잘 작동 :

function getOneLevel($catId){ 
    $query=mysql_query("SELECT categoryId FROM categories WHERE categoryMasterId='".$catId."'"); 
    $cat_id=array(); 
    if(mysql_num_rows($query)>0){ 
     while($result=mysql_fetch_assoc($query)){ 
      $cat_id[]=$result['categoryId']; 
     } 
    } 
    return $cat_id; 
} 

function getChildren($parent_id, $tree_string=array()) { 
    $tree = array(); 
    // getOneLevel() returns a one-dimensional array of child ids   
    $tree = $this->getOneLevel($parent_id);  
    if(count($tree)>0 && is_array($tree)){  
     $tree_string=array_merge($tree_string,$tree); 
    } 
    foreach ($tree as $key => $val) { 
     $this->getChildren($val, &$tree_string); 
    } 
    return $tree_string; 
} 

를 호출 getChildren(yourid); 는 그럼 그 주어진 노드/부모에 대한 자녀의 전체 배열을 반환합니다.

+0

이것은 좋은 일입니다. 아마도이 두 클래스를 모두 클래스로 래핑해야합니다. 또한, $ tree = $ this-> getOneLevel ($ parent_id);' 'foreach ($ tree as $ branch => $ branch_string) { if (in_array ($ branch_string, $ tree_string))} 뒤에 오른쪽에' { unset ($ tree [$ branch]); } } ' 이 코드가 올바르게 표시되지 않습니다. 어떻게 코드 예제로 코멘트합니까? – henrijs

0

array_push($tree, $ids);보다 $tree = array_merge($tree, $ids);을 시도하십시오. $tree_string .= implode(',', $tree);을 죽이고 단지 return $tree을 죽이십시오. (한 번)

function getChildren($parent_id) { 
    $tree = Array(); 
    if (!empty($parent_id)) { 
     $tree = $this->getOneLevel($parent_id); 
     foreach ($tree as $key => $val) { 
      $ids = $this->getChildren($val); 
      a$tree = array_merge($tree, $ids); 
     } 
    } 
    return $tree; 
} 
관련 문제