Nueva pregunta

Pregunta:

Fecha: 03-11-2016 04:29:24 (En Español)

Recursividad en PHP: lectura de directorios, subdiretorios y archivos[Resuelta]

Buen día PHPeros!!

Les describo el problema en el que me encuentro:

Tengo una función en la que intento leer un directorio, subdirectorios y archivos, con la siguiente estructura: DIRECTORIO_PRINCIPAL(en la función es el path que le paso como parametro) > SUBDIRECTORIOS_NIVEL1 > SUBDIRECTORIOS_NIVEL2 > ARCHIVOS. El objetivo es guardar los paths de cada archivo en un vector para poder ser consumidos desde otra función. El problema es que al parecer dentro de mi funcion leerDir() puedo almacenar todos los paths, pero al tomar el vector desde otra función sólo puedo ver los paths de los archivos que se encontraban en el DIRECTORIO_NIVEL1 y no estoy dando con la solución.

A continuación dejo el código de la función leerDir():

public function leerDir($path) { //devuelve un vector con los paths de todos los archivos
    //echo "entro";
    $dir = opendir($path);
    $archivos = array();
    while ($current = readdir($dir)) {
        if ($current != "." && $current != "..") {
            //var_dump($path.'/'.$current);
            if (is_dir($path . '/' . $current)) {
                $this->leerDir($path . '/' . $current);
            } else {
                //var_dump($current);
                $archivos[] = $path . '/' . $current;
            }
        }
    }
    return $archivos;
}


Espero haberme explicado bien. Desde ya muchas gracias!

Saludos!
Diego.
Etiquetas: Desarrollo - PHP - Pregunta Votos: 2 - Respuestas: 2 - Vistas: 13 Compartir en: Google Facebook Twitter LinkedIn Link
 

Respuestas:

  • Fecha: 03-11-2016 08:21:52 Hola Diego, no estabas tan lejos de lograrlo, básicamente te falto acumular los resultados de las llamadas recursivas, y como la variable $archivos vive en cada scope de ejecución como una variable independiente, no estabas ocumulando nada ahí, lo único que retornabas eran los archivos del primer nivel (porque es la única variable que quedaba viva una vez finalizada la ejecución).

    Recomiendo ver el apartado Ámbito de las variables en la documentación oficial de PHP

    Solución al caso: tienes varias, puedes utilizar la palabra reservada global (opción que no es de mi agrado) y/o pasar la variable como nuevo parámetro en cada llamada (la opción que te presento).

    Aquí un ejemplo 100% ejecutable y cross plataforma:
    <?php
    
    class Disco {
    
        /**
         * Devuelve un vector con los paths de todos los archivos
         * @param string $path
         * @param array $archivos
         * @return array
         */
        public static function getPathsArchivos($path, array $archivos = array()) {
            $dir = opendir($path);
            if (!is_array($archivos)) {
                //en la primera ejecución se inicializa el array
                $archivos = array();
            }
            while ($current = readdir($dir)) {
                if ($current != "." && $current != "..") {
                    if (is_dir($path . DIRECTORY_SEPARATOR . $current)) {
                        $archivos = self::getPathsArchivos($path . DIRECTORY_SEPARATOR . $current, $archivos);
                    } elseif (is_file($path . DIRECTORY_SEPARATOR . $current)) {
                        $archivos[] = $path . DIRECTORY_SEPARATOR . $current;
                    }
                }
            }
            return $archivos;
        }
    
    }
    
    //ejemplo de uso:
    $path = dirname(__FILE__); //tomo el path donde esta el archivo (a modo de ejemplo)
    $arrayResultado = Disco::getPathsArchivos($path);
    
    //imprimo el resultado
    echo '<pre>';
    print_r($arrayResultado);
    


    Espero que mi respuesta te sea de ayuda.

    Saludos y buen código!

    --------------------------------------------------

    Extras:
    * Si es verdad que a partir de la versión 5.3.x ya podemos usar la constante predefinida __DIR__ en vez de dirname(__FILE__), pero la idea es que el ejemplo sea lo más "cross platform" posible.
    * Se podría pasar el array $archivos por referencia, incluyendo en la definición de la función el modificador &, no lo hice para no complejizar, pero no estaría de más para optimizar el uso de la memoria.
    * En las últimas versiones de php se puede obviar el uso del parametro por defecto $archivos = NULL y utilizar la combinación de type hinting y los nuevos tipos de datos permitidos: "public static function getPathsArchivos($path, array $archivos = array()) {" con lo cual podríamos obviar la comprobación e inicialización presente en las líneas 13, 14, 15 y 16.
    * Se podría mejorar la lógica para que solo compruebe si es o no un archivo (is_file) y en cualquier otro caso invoque la recursividad... con esto se simplificarían las comprobaciones y pasos.
    * Comentarios? mejoras? (espero sus aportes y ejemplos con código ejecutable).
      Votos: 2 - Link respuesta
     
  • Fecha: 04-11-2016 03:50:46 Buen día Fernando! Muchas gracias por tu detallada respuesta. Ha sido muy útil ya que hace poquito tiempo ando con PHP y desconozco muchas alternativas.

    Saludos!
    Diego.
      Votos: 1 - Link respuesta
     
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión
 
frjcbbae garagebible.com