2017-02-02 82 views
1

我需要使用mysql查詢列出文件夾名稱和子文件夾名稱。子文件夾的深度未知。這是一個父文件夾可能有n級子文件夾。請參考下面的示例文件夾藥結構:使用mysql顯示文件夾結構

-PHP 
    -Developer 
     -Junior 
     -Senior 
    -Tester 
-Java 
    -Test Engineer 
-Android 

的文件夾結構可能會有所不同..

我的表看起來像

enter image description here

我想在選擇要加載的文件夾名稱像父母和他們的孩子的方式。

PHP 
    Developer 
    Junior 
    Senior 
    Tester 
    Java 
    Test Engineer 
    Android 

我試過了嗎?

$fOption=""; 
$parentFolders = $db->query("SELECT * FROM jp_emp_folder WHERE parent_id='0' AND emp_id='".$empId."'"); 
while($parentRows = $db->fetch_array($parentFolders)){ 
    $fOption .= "<option value='".$parentRows['id']."'>".$parentRows['folder_name']."</option>"; 
    $child = $db->query("SELECT * FROM jp_emp_folder WHERE parent_id='".$parentRows['id']."' AND emp_id='".$empId."'"); 
    while($childRows = $db->fetch_array($child)){ 
     $fOption .= "<option value='".$childRows['id']."'>".$childRows['folder_name']."</option>"; 
    } 
} 
echo $fOption; 

我知道這隻給出2級文件夾結構。但我有n級。我該如何實現這個目標?請建議..

+0

關鍵字:* *遞歸。不建議使用這種方法來構建層次結構,因爲DB的開銷很大。如果可能的話,您可以將整個結構轉換爲多維數組。通過遞歸讀取數組,您可以輕鬆高效地構建樹。 – Raptor

+0

遞歸編程可能是一個很好的解決方案。 https://en.wikipedia.org/wiki/Recursion_(computer_science) – Twinfriends

回答

0

您可以使用這種方法來構建您的層次結構。

步驟1:構建了$數據在PHP

​​

步驟2:遞歸讀取$數據來構建分層結構

function readData($parent_id = 0) { 
     global $data; // I'm just lazy, avoid using "global" 
     foreach($data as $id => $item) { 
      if($parent_id > 0 && $item['parent_id'] != $parent_id) { 
       continue; 
      } 
      echo '<option value="' . $id . '">' . $item['folder_name'] . '</option>' . PHP_EOL; 
      unset($data[$id]); // Remove echo-ed contents 
      if($item['parent_id'] > 0) { 
       readData((int)$id); 
      } 
     } 
    } 

readData(); // Start reading $data 

這將輸出以下內容:

<option value="1">PHP</option> 
<option value="2">Java</option> 
<option value="3">Android</option> 
<option value="4">Test Engineer</option> 
<option value="5">Developer</option> 
<option value="7">Junior</option> 
<option value="6">Tester</option> 
+0

'Junior'應該在'Developer'下面 – next2u

+0

爲什麼?你的邏輯是什麼?請解釋。 – Raptor

+0

在我的問題看看錶,'Junior'有'parent_id''5'這是'Developer' – next2u

0

檢查。

$all_folders = $db->query("SELECT * FROM jp_emp_folder WHERE emp_id='".$empId."'"); 
$array_column = array_column($all_folders, 'parent_id');   
$all_parent0_dir = array_keys($array_column, "0"); //get all base folders 

foreach ($all_parent0_dir as $value) { 
    $dir = $all_folders[$value]; 
    echo '<option value="'.$dir['id'].'">'.$dir['foler_name'].'</option>'; 
    $parent_id = $dir['id']; 
    $nodeNumber = 1; 
    $lastElem = FALSE;//is this last element of the folder 
    $nodeArray = [];//save all the nodes of the folder 
    while ($parent_id != $dir['id'] || $lastElem == FALSE) { 
     /*************************************************************/ 
     //get details of a specific folder 
     $last = 1; 
     $sub_dir_ids = array_keys($array_column, $parent_id); 
     if($sub_dir_ids) 
     { 
      $sub_dir = isset($sub_dir_ids[$nodeNumber-1])? $sub_dir_ids[$nodeNumber-1] : null; 
      if($sub_dir){ 
       $res = $all_folders[$sub_dir]; 
       echo '<option value="'.$res['id'].'">'.$res['foler_name'].'</option>'; 
       if($res){$last = 0; }      
      } 
     } 
     /*************************************************************/ 
     if($last == 1){   
      if($parent_id != $dir['id']){//if $parent_id didn't reach the first element (starting point) 
       $lastElement = array_pop($nodeArray); 
       $parent_id = $lastElement[0]; 
       $nodeNumber = $lastElement[1] + 1; 
      }else{$lastElem = TRUE;} 
     }else{ 
      $lastElem = FALSE; 
      array_push($nodeArray, array($parent_id,$nodeNumber)); 
      $parent_id = $res['id'];//$parent_id for inner folder 
      $nodeNumber = 1;//go to next step - inner folder 
     } 
    }    
} 

輸出

<option value="1">PHP</option> 
<option value="5">DEVELOPER</option> 
<option value="7">JUNIOR</option> 
<option value="8">SENIOR</option> 
<option value="6">TESTER</option> 
<option value="2">JAVA</option> 
<option value="4">TEST ENG</option> 
<option value="3">ANDROID</option> 
+0

這很糟糕。不建議過多的DB抓取。 – Raptor

+0

我不明白,你的意思是'過多的DB抓取'。你能解釋一下嗎? – Ruby

+0

是的,在你的每一個遞歸循環中,你查詢DB一次。這會產生大量不必要的查詢,您可以在1個查詢中獲取所有數據。 – Raptor