이번에는 php와 자바스크립트로 트리구조 디렉토리를 구현해 보도록 하겠습니다.
사실 이 소스는 웹하드를 구현할때 유용하게 사용될 수 있습니다.
검색사이트에서 검색을 해보면 알겠지만, 트리형 디렉토리 구현은 쉬운문제는 아니었습니다.
뭐 자바나, C++, 베이직 같은 응용프로그램을 이용하면 금방이지만, 웹에서 서버컴의 디렉토리를 트리형으로 띄우는 문제는 다른문제입니다.
이문제로 삽질할 끝에 저 나름대로 만족할 만한 소스를 구현하였습니다.
구글의 여타 다른소스보다 간결하고, 구현또한 깔끔하고 다이나믹 합니다.(자화자찬 ㅋㅋ!)
우선 첨부파일로 참조한 파일이 필요합니다.
index.php 소스는 다음과 같습니다.
참고로 재귀함수로 구현하였습니다.
php소스를 보기 앞서 최종적으로 HTML로 뿌려지는 결과물은 다음과 같습니다.
<div id="LY_board1" style="height:0px;display:block">
<script> a = new dTree('a'); a.add(0,-1,'My Web Hard'); a.add(1,0,'111'); a.add(2,0,'222'); a.add(3,0,'333'); a.add(4,0,'광주6월11일.csv','','','','img/page.gif'); a.add(5,0,'광주6월12일.csv','','','','img/page.gif'); a.add(6,0,'광주6월13일.csv','','','','img/page.gif'); a.add(7,1,'광주6월19일.csv','','','','img/page.gif'); a.add(8,1,'광주6월20일.csv','','','','img/page.gif'); a.add(9,1,'광주6월23일.csv','','','','img/page.gif'); a.add(10,2,'222-111'); a.add(11,2,'광주6월17일.csv','','','','img/page.gif'); a.add(12,2,'광주6월18일.csv','','','','img/page.gif'); a.add(13,2,'광주6월19일.csv','','','','img/page.gif'); a.add(14,10,'광주6월19일.csv','','','','img/page.gif'); a.add(15,10,'광주6월20일.csv','','','','img/page.gif'); a.add(16,10,'광주6월23일.csv','','','','img/page.gif'); document.write(a); </script>
</div>
==> 여기까지 결과물 HTML 코드
위에서 Mtree.js의 클래스를 이용해 객체를 하나 선언하고
add('증가되는 id값','부모 참조키값(id)','파일명 또는 노드명',...,'파일 또는 노드 이미지')
여기서 a.add(3,0,'333'); 와 같은것은 디렉토리를 표현할때 노드 이미지를 생략하고,
a.add(16,10,'광주6월23일.csv','','','','img/page.gif'); 처럼 파일을 표현할때는 노드 이미지를 기입합니다. 물론 a.add(0,-1,'My Web Hard'); 처럼 최상위 루드는 꼭 존재해야합니다. 최상위 루트는 부모참조가 없기때문에 -1을 넣습니다. 최상위 루트의 id값을 0으로 하였기 때문에 바로 밑 하위디렉토리는 부모참조키값이 모두 0이 겠죠? 코드를 보고 이글 맨 위의 그림을 참조해 분석해 보길 바랍니다.
여기까지는 단순히 결과물 코드에 대해서 알아보았고, 이젠 심장역할을 하는 원 소스에 대해 보겠습니다. 참고로 뿌려주는 것은 자바스크립트고, 자바의 소스를 만드는것은 php입니다. 또한 재귀함수를 이용하였습니다. 자료구조시간에도 배우셨겠지만, 트리구조는 노드를 타고 다녀야 하기때문에 재귀함수를 이용하지 않고서는 구현이 어렵습니다. 왜냐믄 하나의 노드는 부모나 자식의 노드의 깊이를 짐작할수 없기 때문입니다. 타봐야 아는거죠.
<link rel="StyleSheet" href="dtree.css" type="text/css" /> // dtree.js 의 css파일 <script language='javascript' src="dtree.js"></script> // 디렉토리를 웹에 구현해줄 js 파일
<div id="LY_board1" style="height:0px;display:block"> <? if(!$_GET[dir]) $dir=getcwd()."/FileUp";
/* getcwd()함수는 현재 위치한 디렉토리명을 반환합니다. 여기서 현재 index.php가 위치한 디렉토리 값을 반환합니다. /FileUp은 제가 임의로 보여주고 싶은 디렉토리명을 디폴트로 잡은 것입니다. 사실 소스가 있는 디렉토리를 보여줄순 없지 않습니까? */
chdir($dir); //디렉토리 이동
$Seq; //증가 되는 id 값 변수 (add('증가되는 id값','부모 참조키값(id)','파일명 또는 노드명') 을 참고하세요. add('$Seq','부모 참조키값(id)', 로 대체
$arrTmp=array(); // "a.add($Seq,$pk,'$val');" =>(자바스크립트 소스) 를 뿌려줄 버퍼 function GetDirList($dir,$pk) { global $Seq; //재귀함수를 호출해도 증가되는 id 값은 모두가 참조하게 전역변수여만 합니다. global $arrTmp; // 마찬가지로 자바스크립트 출력버퍼도 모두가 쌓을수 있도록 전역변수여만 합니다.
/*
다음 배열은 노드를 디렉토리와 파일로 구분하였습니다. Fn 은 노드명이 들어갈 배열입니다.
Seq는 현재노드의 키값이 저장됩니다. 이값이 있어야지 하위노드가 부모키값을 참조하겠죠?
*/ $arrDFile["Dir"]["Fn"]=array(); $arrDFile["File"]["Fn"]=array(); $arrDFile["Dir"]["Seq"]=array(); $arrDFile["File"]["Seq"]=array();
if (!is_dir($dir)) die (""); //이건 아시죠 디렉토리가 없으면 죽으란 말입니다.
chdir($dir); //부여받은 디렉토리로 이동하라는 말입니다.
$dh=opendir($dir); //디렉토리 핸들을 얻어오고 while (false!==($FolderOrFile = readdir($dh))) { //해당 디렉토리의 파일이나 하위 디렉토리를 읽어옵니다. if($FolderOrFile != "." && $FolderOrFile != ".." && file_ext("$dir/$FolderOrFile") != "php") { if(is_dir($FolderOrFile)) { //디렉토리일 경우는 디렉토리 배열에 디렉토리명을 저장하고 $arrDFile["Dir"]["Fn"][]=$FolderOrFile; } else { //디렉토리가 아닌 파일일경우는 파일 배열에 파일명을 저장하라는 말입니다. $arrDFile["File"]["Fn"][]=$FolderOrFile; } } } closedir($dh); //이제 현재 디렉토리 열람은 끝났으니 핸들을 닫아야 겠죠
asort($arrDFile["Dir"]["Fn"]); //디렉토리 배열을 이름순으로 소팅합니다. asort($arrDFile["File"]["Fn"]); //파일 배열을 이름순으로 소팅합니다. foreach($arrDFile["Dir"]["Fn"] as $key => $val) { //디렉토리 배열을 돌면서 배열의 번지값과 디렉토리 키값 배열의 번지값을 일치 시킵니다. 번지를 같게 해야 해당디렉토리의 키값을 참조할수 있겠죠. $arrDFile["Dir"]["Fn"][번지3]="111"(디렉토리명) 면 $arrDFile["Dir"]["Seq"][번지3]=18(증가되는 id 키값) 여기선 a.add($Seq,$pk,'$val');" 의 $Seq자리 값이 '18' , 즉 111 디렉토리의 키값은 18이라는 것입니다. 111디렉토리의 인텍스 주소는 3번지라는 것이죠. $arrDFile["Dir"]["Fn"] 나 $arrDFile["Dir"]["Seq"] 의 인덱스 주소가 모두 3번지... 설명이 길었죠? 요것이 가장 핵심입니다. 하나의 노드는 같은 인덱스 번지여만 합니다. 그래야 인덱스 번지만으로 다른 정보도 가져올수 있죠.(키값,노드명 등등) $Seq++; // 키값을 하나 증가시키고 $arrDFile["Dir"]["Seq"][$key]=$Seq; //같은 인덱스 주소로 키값을 저장합니다. $arrTmp[]="a.add($Seq,$pk,'$val');"; //최종 버퍼에 자바스크립트 소스를 저장합니다.
} foreach($arrDFile["File"]["Fn"] as $key => $val) { //노드가 파일이라는 부분만 다르고 상동입니다. $Seq++; $arrDFile["File"]["Seq"][$key]=$Seq; $arrTmp[]="a.add($Seq,$pk,'$val','','','','img/page.gif');";
} foreach($arrDFile["Dir"]["Fn"] as $key => $val) { //**핵심**(별5개), 하위 디렉토리를 재귀함수로 탐색합니다.
GetDirList($dir."/".$val,$arrDFile["Dir"]["Seq"][$key]); //이부분(재귀함수 호출) 설명은 여러분의 생각으로 남겨두겠습니다. 어렵지 않으니 생각해 보세요. } } GetDirList($dir,0); // 펑션 실행 , 여기선 $dir은 위에서 설정한 getcwd()."/FileUp" 이 되겠죠, 시작노드의 디폴트 키값은 0이 되겠죠? a.add(0,-1,'My Web Hard'); 에서 키값을 0으로 했으니까. 이 펑션을 실행하면 $arrTmp 배열에 자바스크립트 소스를 쌓겠죠? ?> <script> a = new dTree('a'); a.add(0,-1,'My Web Hard'); <? foreach($arrTmp as $val) { //버퍼를 돌면서 저장된 자바스크립트 소스를 뿌려줍니다. echo $val; } ?> document.write(a); //최종 객체 출력 </script> </div>
소스를 정리하면 이렇습니다. 디렉토리와 파일로 구분해서 먼저 디렉토리를 뿌려주고 파일을 뿌려주고 그런다음 디렉토리들은 하나씩 재귀함수로 탐색해 나가는 것입니다. 재귀함수로 호출된 디렉토리는 똑같이 하위 디렉토리와 파일을 분리해서 뿌려주고 자신의 하위디렉토리를 재귀함수로 탐색하고, 그렇게 맨 바닥노드까지 탐색하면 종료되고, 최상위 루트의 다음 디렉토리가 하위 노드 탐색을 시작하고... 이런식입니다.
주석을 제거한 소스는 다음과 같습니다.
<link rel="StyleSheet" href="dtree.css" type="text/css" />
<script language='javascript' src="dtree.js"></script>
<div id="LY_board1" style="height:0px;display:block"> <?
function file_ext($ff) { $filename=explode(".",$ff); $file_ext=$filename[sizeof($filename)-1]; return $file_ext; }
if(!$_GET[dir]) $dir=getcwd()."/FileUp"; chdir($dir);
$Seq; $arrTmp=array(); function GetDirList($dir,$pk) { global $Seq; global $arrTmp; $arrDFile["Dir"]["Fn"]=array(); $arrDFile["File"]["Fn"]=array(); $arrDFile["Dir"]["Seq"]=array(); $arrDFile["File"]["Seq"]=array();
if (!is_dir($dir)) die ("");
chdir($dir);
$dh=opendir($dir); while (false!==($FolderOrFile = readdir($dh))) { if($FolderOrFile != "." && $FolderOrFile != ".." && file_ext("$dir/$FolderOrFile") != "php") { if(is_dir($FolderOrFile)) { $arrDFile["Dir"]["Fn"][]=$FolderOrFile; } else { $arrDFile["File"]["Fn"][]=$FolderOrFile; } } } closedir($dh);
asort($arrDFile["Dir"]["Fn"]); asort($arrDFile["File"]["Fn"]); foreach($arrDFile["Dir"]["Fn"] as $key => $val) { $Seq++; $arrDFile["Dir"]["Seq"][$key]=$Seq; $arrTmp[]="a.add($Seq,$pk,'$val');";
} foreach($arrDFile["File"]["Fn"] as $key => $val) { $Seq++; $arrDFile["File"]["Seq"][$key]=$Seq; $arrTmp[]="a.add($Seq,$pk,'$val','','','','img/page.gif');";
} foreach($arrDFile["Dir"]["Fn"] as $key => $val) {
GetDirList($dir."/".$val,$arrDFile["Dir"]["Seq"][$key]); } } GetDirList($dir,0); ?> <script> a = new dTree('a'); a.add(0,-1,'My Web Hard'); <? foreach($arrTmp as $val) { echo $val; } ?> document.write(a); </script> </div>
|