PHP 재귀 기능 결과 수집 : 파일 시스템 스캐너 구축
소개 : 재귀 및 결과 수집의 도전
재귀는 특히 트리 구조 또는 파일 시스템과 같은 자체 유사 구조로 데이터를 처리하기 위해 기능이 스스로 전화하여 문제를 해결할 수있는 강력한 프로그래밍 기술입니다. 그러나 결과를 수집하고 집계하는 결과는 재귀적인 호출에 종종 문제가 발생합니다. 다중 재귀 수준으로 데이터를 축적 해야하는 경우, 모든 하위 국민의 결과를 올바르게 전달하고 최종 결과 세트로 병합 할 수 있는지 확인하는 방법은 개발자에게 핵심 문제입니다.
일반적인 오류 분석 : 어레이를 직접 통과하는 것이 유효하지 않은 이유는 무엇입니까?
많은 초보자는 재귀 함수에서 데이터를 수집하려고 할 때 일반적인 문제를 겪습니다. 배열을 재귀 함수에 대한 인수로 전달하고 기능 내부를 수정하여 모든 재귀 수준에서 데이터를 축적 할 것으로 기대합니다.
다음 코드 스 니펫을 고려하십시오 (원래 질문에 따라) :
function readdirs ($ path, $ result = []) // $ result는 기본적으로 값별로 전달됩니다. $ dirhandle = opendir ($ path); while ($ item = readdir ($ dirhandle)) {{ $ newPath = $ path. "/". $ 항목; if (is_dir ($ newPath) && $ item! = '.'&& $ item! = '..') {{ readdirs ($ newPath, $ result); // 재귀 적으로 전화, $ result의 사본을 전달}} elseif (! is_dir ($ newPath) && $ item! = '.ds_store'&& $ item! = '.'&& $ item! = '..'). {{ // echo "$ path <br>"; // 현재 디렉토리 경로를 인쇄하여 $ result [] = $ path; // 현재 함수의 $ result 사본을 수정하십시오. return $ result; // 조기 반환은 현재 디렉토리의 스캔을 방해하고 부모의 결과에 대한 기대를 방해합니다} } // 파일이 없거나 파일이 현재 디렉토리에 처리 된 경우, 암시 적으로 NULL 또는 빈 $ result를 반환합니다. }
문제 분석 :
- 통과 가치 : PHP에서 기능 매개 변수는 기본적으로 값으로 전달됩니다. 즉, readDirs ($ newPath, $ result)가 호출되면 $ 결과 배열의 사본이 하위 기능으로 전달됩니다. 자식 함수의 $ 결과 사본에 대한 수정은 부모 함수의 원래 $ 결과 배열에 영향을 미치지 않습니다. 따라서 결과는 재귀 호출 사이에 축적 될 수 없습니다.
- 조기 반환 : 반품 $ 결과; elseif 블록의 명령문은 첫 번째 파일을 찾은 직후에 기능이 종료되고 디렉토리 경로를 $ 결과에 추가합니다. 이는 현재 디렉토리에서 다른 파일 및 하위 디렉토리를 스캔하는 것을 방지 할뿐만 아니라 부모 통화가 데이터 수집을 계속할 수 없습니다.
솔루션 코어 : 함수 리턴 값을 사용한 집계 결과
위의 문제를 해결하기위한 핵심은 사고 방식을 변경하는 것입니다. 재귀 함수는 결과를 축적하기 위해 전달 된 배열 매개 변수를 수정하는 데 의존해서는 안되지만 현재 수준에서 수집 한 결과를 반환 해야합니다. 학부모 발신자는 자녀가 반환 한 결과를 수신하고 자체 결과 세트로 병합 할 책임이 있습니다.
이 접근법은 각 함수 호출에 명확한 책임이되도록합니다. 현재 레벨에서 데이터를 처리하고 현재 레벨 및 모든 하위 수준 집계의 결과를 포함하는 전체 데이터 세트를 반환합니다.
효율적인 파일 경로 수집기를 구축하십시오
다음은 지정된 디렉토리 및 모든 하위 디렉토리를 스캔하도록 설계된 최적화 된 PHP 재귀 기능 예제입니다.
php /** * 지정된 디렉토리 및 하위 디렉토리를 재귀 적으로 스캔하여 모든 파일의 전체 경로를 수집합니다. * * @Param String $ 경로 시작 디렉토리를 스캔하는 경로입니다. * 모든 파일의 전체 경로를 포함하는 @return 배열. */ 함수 getAllFilePathSrecursive (String $ Path) : 배열 {{ $ allFilePaths = []; // 현재 레벨의 결과 배열 초기화 // 경로가 유효한 지 확인하고 개방형 디렉토리 인 경우 (! is_dir ($ path) ||! ($ dirhandle = opendir ($ path)) { // 경로가 유효하지 않거나 디렉토리를 열 수없고, 빈 배열 ERRAY_LOG를 반환합니다 ( "디렉토리를 열 수 없음 :". $ 경로); $ allfilepaths를 반환합니다. } while (false! == ($ item = readdir ($ dirhandle))) { // 현재 디렉토리를 건너 뜁니다. 그리고 이전 디렉토리 '..' if ($ item === '.'|| $ item === '..') { 계속하다; } // 크로스 플랫폼 디렉토리 분리기를 사용하여 완전한 새로운 경로를 구축하십시오. $ newPath = $ 경로. directory_separator. $ 항목; if (is_dir ($ newPath)) { // 디렉토리 인 경우, 재귀 적으로 호출하고 반환 된 결과를 현재 결과 번호와 결합하고 // Array_Merge는 배열을 평평하게하여 $ allFilePaths = array_merge ($ allFilePaths, getAllFilePathSRecursive ($ newPath)); } 또 다른 { // 파일 인 경우 결과 배열에 전체 경로를 추가하십시오. // 다른 파일 필터링 조건을 필요에 따라 추가 할 수 있습니다. if ($ item! == '.ds_store') {// macOS의 숨겨진 파일 제외 $ allFilePaths [] = $ newPath; } } } Closedir ($ dirhandle); // 디렉토리 핸들을 닫고 리소스를 릴리스합니다 $ allFilePaths; // 현재 레벨에서 수집 된 모든 파일 경로를 반환} // 예제 사용 : $ basepath = "/user/mycomputer/documents/www/photos_projets"; // 실제 경로로 교체하십시오 // 시작 경로가 존재하는지 확인하고 (! is_dir ($ basepath)) {디렉토리인지 확인하십시오. Echo "오류 : 시작 경로는 존재하지 않거나 디렉토리가 아닙니다. \ n"; } 또 다른 { $ collectedFilePaths = getAllFilePathSrecursive ($ basepath); echo "--- 수집 된 파일 경로 --- \ n"; if (빈 ($ collectedFilePaths)) { Echo "파일이 없습니다. \ n"; } 또 다른 { foreach ($ collectedfilepaths as $ filepath) { Echo $ FilePath. "\N"; } 에코 "총 수집". 카운트 ($ collectedFilePaths). "파일. \ n"; } // var_dump ($ collectedFilePaths)를 사용할 수도 있습니다. 배열 구조를 보려면} ?>
코드 구문 분석 :
- $ allFilePaths = []; : 각 함수 호출의 시작 부분에 로컬 빈 배열을 초기화하십시오. 이 배열은 스캔 된 모든 파일 경로를 현재 계층 구조에 저장하는 데 사용됩니다.
- 오류 처리 : IS_DIR 및 OPENDIR에 대한 확인이 추가되어 경로가 효과적이고 작동하는지 확인하고 견고성을 향상시킵니다.
- Directory_Separator : PHP 내장 Constant Directory_separator를 사용하여 경로를 구축하여 Windows 및 Unix-Like 시스템과 같은 다양한 운영 체제에서 코드의 호환성을 보장합니다.
- 재귀 호출 및 병합 :
- 하위 디렉토리가 발생하면 (IS_DIR ($ NEWPATH)) 기능은 재귀 적으로 getAllFilePathSrecursive ($ NewPath)를 호출합니다.
- 서브 콜은 수집하는 모든 파일 경로의 배열을 반환합니다.
- Array_merge ($ allfilepaths, ...)는 하위 콜에 의해 반환 된 배열을 현재 레벨의 $ allfilepaths와 병합합니다. Array_Merge의 주요 역할은 두 개 이상의 숫자를 새 배열로 결합하여 평평하게하고 중첩 어레이 구조의 결과를 피하는 것입니다.
- 파일 처리 : 파일이 발생하면 (다른 블록) 파일의 전체 경로를 $ allfilepaths에 직접 $ newPath의 전체 경로를 추가하십시오.
- ClosedIR ($ dirhandle) : 기능이 끝나기 전에 디렉토리 핸들을 닫는 것은 시스템 리소스를 확보하기위한 좋은 프로그래밍 습관입니다.
- $ allfilepaths를 반환합니다. : 이것은 가장 중요한 단계입니다. 각 getAllFilePathSRecursive 호출은 현재 계층 구조에서 수집 한 전체 파일 경로와 모든 하위 계층 구조를 반환해야합니다. 이런 식으로, 부모 통화는 이러한 결과를 받고 집계 할 수 있습니다.
메모 및 모범 사례
- 메모리 관리 : 매우 크거나 깊은 파일 시스템의 경우, 재귀 통화는 스택 오버플로 또는 메모리 오버플로를 유발하기 위해 수집 된 경로 수를 유발할 수 있습니다. PHP에서는 일반적으로 memory_limit 및 xdebug.max_nesting_level (xdebug를 사용하는 경우)을 추가하여 완화됩니다. 그러나 이것은 기본 솔루션이 아닙니다. 극단적 인 경우, 메모리 사용을 최적화하기 위해 반복적 인 방법 (예 : splfileobject, recursivedirectoryiterator) 또는 PHP 7 생성기 (수율)를 사용하는 것을 고려하십시오.
- 오류 처리 : 생산 환경에서 Opendir 및 ReadDir와 같은 기능의 가능한 실패를 캡처하고 기록하는 것과 같은보다 완전한 오류 처리 메커니즘을 추가해야합니다.
- 성능 고려 사항 : Array_Merge는 재발 할 때마다 새 배열을 만듭니다. 이는 대규모 파일에 대한 특정 성능 오버 헤드를 가져올 수 있습니다. 성능이 매우 중요한 요소 인 경우, 외부로 배열을 정의하고 참조를 통해 재귀 함수 (Function & ReadDirs ($ path, & $ result))로 전달하는 것을 고려하십시오. 그러나 이는 코드의 복잡성과 잠재적 부작용을 증가시켜 일반적으로 선호하는 선택으로 권장되지 않습니다.
- 디렉토리 분리기 : 항상 Directory_Separator를 사용하여 다른 운영 체제에서 코드의 휴대 성을 보장합니다.
- 필터링 조건 : 실제 요구에 따라 파일 확장, 크기, 수정 시간 등을 기반으로 필터링과 같은 파일 및 디렉토리 처리 로직에 더 많은 필터링 조건을 유연하게 추가 할 수 있습니다.
요약
PHP 재귀 함수에서 결과를 올바르게 수집하고 집계하는 핵심은 함수 매개 변수의 값 전송 메커니즘을 이해하고 함수의 반환 값을 능숙하게 활용하는 것입니다. 각각의 재귀 통화가 처리 된 결과를 반환하면 부모 통화가 이러한 결과를 병합 할 책임이 있으므로 강력하고 효율적인 재귀 알고리즘을 구축 할 수 있습니다. 이 튜토리얼에서 제공하는 파일 시스템 스캔 예제는 재귀 결과 컬렉션의 문제를 해결할뿐만 아니라 실제 애플리케이션에서 전문적이고 유지 관리 가능한 PHP 코드를 작성하는 방법을 보여줍니다.
위 내용은 PHP 재귀 기능 결과 수집 : 파일 시스템 스캐너 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undress AI Tool
무료로 이미지를 벗다

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Stock Market GPT
더 현명한 결정을 위한 AI 기반 투자 연구

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

usefilter_var () tovalidateemailsyntaxandcheckdnsrr () toverifydomainmxrecords.example : $ email = "user@example.com"; if (f ilter_var ($ 이메일, filter_validate_email) && checkdnsrr (Explode ( '@', $ email) [1], 'mx')) {echo "validandDeliverableEmail & qu

AseUnserialize (Serialize ($ obj))는 AllDataisserializable 이하의 경우 FordeepCopying; 그렇지 않으면, ubstract__clone () tomanuallyduplicateNestEdObjectSandavoidshartReferences.

USEARRAY_MERGE () TOCOMBINEARRAYS, DUCRITINGDUPLICATESTRINGKEYSANDENTEXINGUMERICEYS; FORSIMPLERCONCATENATION, 특히 인포드 55.6, USETHESPLATOPERATOR [... $ array1, ... $ array2].

이 기사에서는 케이스 문을 사용하여 MySQL에서 조건부 집계를 수행하여 특정 필드의 조건부 합산 및 계산 방법에 대해 자세히 설명합니다. 실제 구독 시스템 사례를 통해 레코드 상태 (예 : "END"및 "CANCEL"과 같은 총 기간 및 이벤트 수를 동적으로 계산하여 복잡한 조건부 집계의 요구를 충족시킬 수없는 전통적인 합계 기능의 한계를 극복하는 방법을 보여줍니다. 튜토리얼은 합 함수로 사례 문의 적용을 자세히 분석하고 왼쪽 조인의 가능한 널 값을 다룰 때 Coalesce의 중요성을 강조합니다.

네임 스페이스 인 네임 스페이스 inphorganizecodecodecodeandnamingnamingconflictsbygroupingclasses, 인터페이스, 함수, andconstantsOnspecificname.2.defineanamesUsUsingThenamesPaceyWordAtTHETOPOFOFILE, AFFORBINSPACENAME, suchATESKEYSTOI

The__call ()는 MethodsibleorundorundeRunded에서 정의 될 때 MethodStrigged를 정의하고, themodnameandarguments, asshowningwhendingderdefinedmethodslikesayhello ()

useathinfo ($ filename, pathinfo_extension) togetThefileExtension; itreliablyHandleSmultipledOtsededGecases, returningTheextension (예 : "pdf") oranEmptyStringifnoneExists.

toupdateadaBasereCordInphp, FirstConnectusingpdoorMysqli, whenEseprepredStatementStoExecuteAcureCuresqlupDateQuery.example : $ pdo = newpdo ( "mysql : host = localhost; dbname = your_database", $ username, $ username, $ sql = "squer erestemail);
