


PHP Recursive Fonction Results Collection: Construire un scanner de système de fichiers
Introduction: le défi de la collection de la récursivité et des résultats
La récursivité est une puissante technique de programmation qui permet aux fonctions de résoudre des problèmes en s'appelant, en particulier pour le traitement des données avec des structures auto-similaires, telles que les structures d'arbres ou les systèmes de fichiers. Cependant, la collecte et l'agrégation des résultats en appels récursifs rencontrent souvent des défis. Lorsque les données doivent être accumulées dans plusieurs niveaux récursifs, comment s'assurer que les résultats de tous les sous-appels peuvent être correctement transmis et fusionnés dans l'ensemble de résultats finaux est un problème clé pour les développeurs.
Analyse des erreurs courantes: pourquoi est-il invalide de passer directement les tableaux?
De nombreux débutants rencontrent un problème commun lorsque vous essayez de collecter des données à partir de fonctions récursives: passer un tableau comme argument à la fonction récursive et s'attendre à les modifier à l'intérieur de la fonction pour accumuler des données à tous les niveaux récursifs.
Considérez l'extrait de code suivant (basé sur la question d'origine):
Fonction ReadDirs ($ path, $ result = []) // $ Le résultat est passé par valeur par défaut { $ dirhandle = opendir ($ path); tandis que ($ item = readdir ($ dirhandle)) { $ newpath = $ path. "/". $ item; if (is_dir ($ newpath) && $ item! = '.' && $ item! = '..') { ReadDirs ($ newpath, $ Result); // Appel récursivement, passant une copie de $ result} elseif (! is_dir ($ newpath) && $ item! = '.ds_store' && $ item! = '.' && $ item! = '..') { // écho "$ path <br>"; // Imprime le répertoire actuel Path $ Result [] = $ path; // Modifiez la copie de résultat $ de la fonction actuelle Retour $ Résultat; // Renvoie prématurément interrompre le scan du répertoire actuel et interrompt l'attente du parent du résultat} } // s'il n'y a pas de fichier ou si le fichier est traité dans le répertoire actuel, il renverra implicitement Null ou Vide $ Résultat }
Analyse des problèmes:
- Passer par valeur : en php, les paramètres de fonction sont passés par valeur par défaut. Cela signifie que lorsque ReadDirs ($ newPath, $ result) est appelé, une copie du tableau de résultat $ est transmise à la sous-fonction. Toute modification de la copie de résultat $ par la fonction enfant n'affectera pas le tableau de résultat $ d'origine dans la fonction parent. Par conséquent, le résultat ne peut pas être accumulé entre les appels récursifs.
- Retour prématuré : le résultat de retour $; L'instruction dans le bloc ELLEIF fera quitter la fonction immédiatement la sortie après avoir trouvé le premier fichier et ajouté le chemin du répertoire vers $ le résultat. Cela empêche non seulement la numérisation d'autres fichiers et sous-répertoires dans le répertoire actuel, mais il est également impossible pour l'appel parent de continuer à collecter des données.
Core de solution: Résultats agrégés à l'aide de valeurs de retour de fonction
La clé pour résoudre le problème ci-dessus est de modifier la manière de penser: la fonction récursive ne doit pas s'appuyer sur la modification des paramètres du tableau passé pour accumuler les résultats, mais doit renvoyer les résultats qu'il a collectés au niveau actuel. L'appelant parent est responsable de la réception des résultats renvoyés par l'enfant et de la fusion dans son propre ensemble de résultats.
Cette approche garantit que chaque appel de fonction a des responsabilités claires: le traitement des données au niveau actuel et le renvoi d'un ensemble de données complet contenant les résultats du niveau actuel et de tous les agrégats de sous-niveau.
Construisez un collecteur de chemins de fichiers efficace
Voici un exemple de fonction récursif PHP optimisé conçu pour scanner un répertoire spécifié et tous ses sous-répertoires et renvoyer un tableau aplati contenant les chemins complets de tous les fichiers (non-répertoires).
Php / ** * Analyser récursivement le répertoire spécifié et ses sous-répertoires pour collecter le chemin complet vers tous les fichiers. * * @param String $ chemin le chemin du chemin pour scanner le répertoire de démarrage. * @return Array contenant les chemins complets de tous les fichiers. * / fonction getallFilepathSRecursive (String $ path): Array { $ allFilePaths = []; // Initialisez le tableau de résultat du niveau actuel // Vérifiez si le chemin est valide et est un répertoire ouvert if (! Is_dir ($ path) ||! ($ Dirhandle = opendir ($ path))) { // Le chemin est invalide ou le répertoire ne peut pas être ouvert, renvoyant le tableau vide error_log ("Impossible d'ouvrir le répertoire:". $ Path); retour $ AllFilepaths; } while (false! == ($ item = readdir ($ dirhandle))) { // ignore le répertoire actuel '.' et le répertoire précédent '..' if ($ item === '.' || $ item === '..') { continuer; } // Créez un nouveau chemin complet, en utilisant le séparateur de répertoire multiplateforme $ newpath = $ path. Directory_separator. $ article; if (is_dir ($ newpath)) { // S'il s'agit d'un répertoire, appelez lui-même de manière récursive et combinez le résultat renvoyé avec le numéro de résultat actuel et // array_merge est utilisé pour aplatir le tableau pour éviter de nicher $ allFilepaths = array_merge ($ allFilepathes, getAllFilePathSrecursive ($ newPathe)); } autre { // S'il s'agit d'un fichier, ajoutez son chemin complet au tableau de résultat // D'autres conditions de filtrage de fichiers peuvent être ajoutées au besoin, comme l'exclusion .ds_store if ($ item! == '.ds_store') {// exclure les fichiers cachés de macOS $ allFilePaths [] = $ newPath; } } } CLOLIRIR ($ dirhandle); // Fermez la poignée du répertoire et libérez le retour de ressources $ AllFilePaths; // renvoie tous les chemins de fichier collectés au niveau actuel} // Exemple d'utilisation: $ basepath = "/ utilisateurs / myComputer / Documents / www / Photos_projet"; // Veuillez le remplacer par votre chemin réel // Vérifiez si le chemin de départ existe et est un répertoire if (! Is_dir ($ basepath)) { Echo "Erreur: le chemin de départ n'existe pas ou n'est pas un répertoire. \ n"; } autre { $ CollectedFilePaths = GetAllFilePathSrecursive ($ basepath); echo "--- le chemin du fichier collecté --- \ n"; if (vide ($ collectéfilepaths)) { echo "aucun fichier trouvé. \ n"; } autre { foreach ($ collectéfilepaths comme $ filepath) { Echo $ filepath. "\ n"; } Echo "collecté au total". Count ($ collectéfilepaths). "fichiers. \ n"; } // Vous pouvez également utiliser var_dump ($ collectéFilePaths); Pour afficher la structure du tableau} ?>
Analyse de code:
- $ allFilePaths = []; : Initialisez un tableau vide local au début de chaque appel de fonction. Ce tableau sera utilisé pour stocker tous les chemins de fichier analysés vers la hiérarchie actuelle.
- Gestion des erreurs : Ajout de vérifications sur IS_DIR et OpenDir pour s'assurer que le chemin est efficace et opérationnel, et améliore la robustesse.
- Directory_Separator : Utilisez PHP constant intégré Directory_Separator pour créer le chemin d'accès, ce qui garantit la compatibilité du code sur différents systèmes d'exploitation tels que Windows et Unix-Like Systems.
- Appels récursifs et fusion :
- Lorsqu'un sous-répertoire est rencontré (IS_DIR ($ newpath)), la fonction appellera récursivement getAllFilePathSrecursive ($ newpath).
- Le sous-appel renvoie un tableau de tous les chemins de fichier qu'il collectionne.
- Array_merge ($ AllFilePaths, ...) Fumente le tableau renvoyé par le sous-appel avec les $ AllFilePaths du niveau actuel. Le rôle clé de Array_merge est qu'il combine deux nombres ou plus dans un nouveau tableau, l'aplatirant ainsi et évitant le résultat d'une structure de réseau imbriquée.
- Traitement de fichiers : lorsqu'un fichier est rencontré (Else Block), ajoutez le chemin complet du fichier $ newpath directement à $ AllFilePaths.
- CLOLIRIR ($ dirhandle) : fermé la poignée du répertoire avant la fin de la fonction est une bonne habitude de programmation pour libérer les ressources système.
- retour $ AllFilepaths; : C'est l'étape la plus critique. Chaque appel GetAllFilePathSrecursive doit renvoyer le tableau complet des chemins de fichier qu'il a collectés dans la hiérarchie actuelle et toutes ses sous-hiérarchies. De cette façon, l'appel parent peut recevoir et agréger ces résultats.
Notes et meilleures pratiques
- Gestion de la mémoire : pour les systèmes de fichiers très grands ou profonds, les appels récursifs peuvent provoquer un débordement de pile ou un nombre excessif de chemins collectés pour provoquer un débordement de mémoire. En PHP, il est généralement atténué en ajoutant Memory_limit et xdebug.max_nesting_level (si vous utilisez xdebug), mais ce n'est pas la solution fondamentale. Pour les cas extrêmes, envisagez d'utiliser des méthodes itératives (telles que SPLFileObject, RecursiveDirectoryiterator) ou le générateur PHP 7 (rendement) pour optimiser l'utilisation de la mémoire.
- Gestion des erreurs : Dans les environnements de production, des mécanismes de gestion des erreurs plus complets doivent être ajoutés, tels que la capture et la journalisation de l'échec possible des fonctions telles que OpenDir et Readdir.
- Considérations de performances : Array_merge crée un nouveau tableau à chaque fois qu'il se reproduit, ce qui peut apporter certaines frais généraux de performances pour les fichiers massifs. Si les performances sont un facteur extrêmement critique, envisagez de définir un tableau à l'extérieur et de le passer à une fonction récursive (fonction et readdirs ($ path, & $ result)) par référence, mais cela augmente la complexité du code et des effets secondaires potentiels, qui n'est généralement pas recommandé comme choix préféré.
- Séparateur de répertoire : utilisez toujours Directory_Separator pour assurer la portabilité du code sur différents systèmes d'exploitation.
- Conditions de filtrage : Selon les besoins réels, vous pouvez ajouter de manière flexible les conditions de filtrage à la logique de traitement du fichier et du répertoire, telles que le filtrage en fonction de l'extension du fichier, de la taille, du temps de modification, etc.
Résumer
La clé de la collecte et de l'agrégation correctes dans les fonctions récursives PHP est de comprendre le mécanisme de transfert de valeur des paramètres de fonction et d'utiliser habilement la valeur de retour de la fonction. En ayant chaque appel récursif renvoie les résultats qu'il traite et l'appel parent est responsable de la fusion de ces résultats, nous pouvons créer un algorithme récursif robuste et efficace. Les exemples de numérisation du système de fichiers fournis par ce didacticiel résolvent non seulement le problème de la collection de résultats récursifs, mais montrent également comment rédiger un code PHP professionnel et maintenable dans des applications pratiques.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Stock Market GPT
Recherche d'investissement basée sur l'IA pour des décisions plus intelligentes

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Usefilter_var () tovalidateemailsyntaxandcheckdnsrr () toverifydomainmxrecords.example: $ email = "user@example.com"; if (f ilter_var ($ e-mail, filter_validate_email) && checkdnsrr (explosage ('@', $ e-mail) [1], 'mx')) {echo "ValidAndDeliverableMail & Qu

UseUnserialize (serialize ($ obj)) FordopcopyingwhenallDataisSerializable; Sinon, implémentez__Clone () TomanuallyDuplicatesedObjectsAndavoidSharedReferences.

UseArray_merge () toCombineArrays, écrasant leduplicatestringKeysAndreIndexingNumericKeys; ForsimplecCaTencatenation, en particulierInphp5.6, usethesplatoperator [... $ array1, ... $ array2].

Cet article explique en profondeur comment utiliser les instructions de cas pour effectuer une agrégation conditionnelle dans MySQL pour atteindre la sommation conditionnelle et le comptage de champs spécifiques. Grâce à un cas de système d'abonnement pratique, il montre comment calculer dynamiquement la durée totale et le nombre d'événements en fonction de l'état des enregistrements (tels que "end" et "annuler"), surmontant ainsi les limites des fonctions de somme traditionnelles qui ne peuvent pas répondre aux besoins d'une agrégation conditionnelle complexe. Le tutoriel analyse en détail l'application des instructions de cas en détail et souligne l'importance de la fusion lorsqu'il s'agit des valeurs nulles possibles de la jointure gauche.

NamespacesInphporganizEcodeAndPreventnamingConflictsBygroupingClasses, Interfaces, Functions et ConstantsunSunSaspecificName.2.DefineanamespaceusingTheNamesPaceSpaceKeyWordAtTopofaFile, suiviByTheNamesPacename, Suchasapp \ Controlers...USUSEUSEKEYWORDTOI

La méthodiette () méthodiste axée sur le point de réviser la mise en œuvre de l'inscription, ce qui permet de faire de la maintenance à la qualité de qualité et

ToupDateAdatabasereCorDinPhp, FirstConnectUsingPDoOrmysQLi, theNusepreparedStationStoExECUSEASECURSQLUPDATEQUERY.example: $ pdo = newPDO ("MySql: host = localhost; dbname = votre_database", $ username, $ mot de passe); $ sql = "dameussem =.

UsePathinfo ($ nom de fichier, pathinfo_extension) togetThefileExtension; itreliabblyHandlesMultipledototsEdGasases, renvoyantTheExtension (par exemple, "pdf") oranemptystringefNoneExists.
