PHP 계정에서 다음과 같은 구조로 파일이 존재하고 있습니다.

목표는 files 디렉토리(폴더) 내에 있는 파일들을 탐색하고, 파일들의 정보(이름, 확장자, 크기 등)를 표시 및 데이터베이스 테이블에 입력하는 것입니다. 핵심 코드는 아래와 같습니다.

$dir = './files';
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));

$dir은 탐색 대상 디렉토리의 루트 경로를 입력합니다. 현재 작성중인 php 파일과 files 디렉토리가 같은 경로 내에 있으므로 위와 같이 입력하였습니다. 일단 RecursiveDirectoryIterator는 이름을 보면 파일 시스템 내부를 재귀적으로 탐색하는 역할을 하는 것처럼 보이고, 실제로 그 역할이 맞습니다. 다만 new RecursivesiveDirectoryIterator(경로)를 단독으로 사용하면 원하는 결과가 나오지 않습니다.

// 잘못된 코드: 루트 디렉토리의 내용만 출력됨
$iterator = new RecursiveDirectoryIterator($dir);

단독으로 사용할 경우 files 디렉토리 정보만 출력하고 하위 디렉토리는 출력되지 않습니다. 이것을 RecursiveIteratorIterator라는 클래스의 인스턴스로 한 번 감싸고 실행해야 실제로 재귀 탐색을 수행합니다. 클래스 이름이 이상한데 풀어쓰면 RecursiveIterator의 Iterator입니다. 굳이 이렇게 작성해야 하는 이유는 이 글(영문)을 참고해주세요.

이제 $iterator는 파일 및 디렉토리의 정보들을 담고 있습니다. 이것을 foreach문으로 처리하면 됩니다.

<?php
    // DB 초기화 작업
    (...)
    if(!$mysqli){        
        echo "MySQL 접속 실패: ";
    } 

    function iterateDirectory($i, $mysqli)
    {

        foreach ($i as $path) {
            if ($path->isDir())
            {
                iterateDirectory($path, $mysqli);
            }
            else
            {
                $r_path = str_replace("\\", "/", $path);
                $v_path = str_replace("./files/", "", $r_path);
                
                $basename = $path->getBasename();
                $real_path = str_replace("./files", "", $path->getPath());
                $extension = $path->getExtension();
                $disp_name = str_replace(".".$extension, "", $basename);
                $a_time = $path->getATime();
                $c_time = $path->getCTime();
                $m_time = $path->getMTime();
                $a_date = date("Y-m-d H:i:s", $a_time);
                $c_date = date("Y-m-d H:i:s", $c_time);
                $m_date = date("Y-m-d H:i:s", $m_time);
                $size = $path->getSize();
                $type = $path->getType();

                echo "<tr>";
                echo "<td>".$basename;
                echo "<td>".$real_path;
                echo "<td>".$extension;
                echo "<td>".$disp_name;
                echo "<td>".$a_date;
                echo "<td>".$c_date;
                echo "<td>".$m_date;
                echo "<td>".$size;
                echo "<td>".$type; 
                
                
                $sql = "INSERT INTO `music_midi_files`"
                ."(`id`, `disp_name`, `basename`, `path`, `extension`, "
                ."`a_time`, `c_time`, `m_time`, `size`, `type`, `reg_dt`, `is_work`) VALUES "
                ."(0,'$disp_name','$base_name','$real_path','$extension',"
                ."'$a_date','$c_date','$m_date','$size','$type',sysdate(),1)";
                
                 if($mysqli->query($sql)) {
                    echo "<td><span style='color:green;'>success</span>";
                 } else {
                    echo "<td><span style='color:red;'>failure</span>";
                 }
                 echo "</tr>";

            }
        }       

    }

    $dir = './files';
    $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));

    iterateDirectory($iterator, $mysqli);

?>

데이터베이스 초기화 작업에 대한 코드는 생략합니다. 이 글을 참고해주세요. 재귀 탐색을 위해 iterateDirectory라는 함수를 만들었습니다. 이 안에 $iterator에 대한 foreach문을 실행합니다. $path가 디렉토리라면 해당 함수를 재귀호출하고, 아니라면(=파일이라면) 파일 정보를 표시하고 sql의 insert문을 실행합니다. 참고로 $path의 타입은 FilesystemIterator입니다. (바로 가기(영문))

위에서 언급했던 문제되는 부분이 이 if문인데 ReursiveDirectoryIterator의 결과는 여기서 디렉토리라는 것을 인지하고 그 이후 탐색해야 할 정보도 가지고 있습니다. 다만 $path를 파라미터로 하는 함수를 호출해도 작업을 수행하지 못합니다.

문의 | 코멘트 또는 yoonbumtae@gmail.com


카테고리: WEB: BackendPHP


0개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다