Deep Recursive Array of Directory Structure in PHP

Deep recursive array of directory structure in PHP

I recommend using DirectoryIterator to build your array

Here's a snippet I threw together real quick, but I don't have an environment to test it in currently so be prepared to debug it.

$fileData = fillArrayWithFileNodes( new DirectoryIterator( '/path/to/root/' ) );

function fillArrayWithFileNodes( DirectoryIterator $dir )
{
$data = array();
foreach ( $dir as $node )
{
if ( $node->isDir() && !$node->isDot() )
{
$data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
}
else if ( $node->isFile() )
{
$data[] = $node->getFilename();
}
}
return $data;
}

PHP: How to populate a directory structure in an array

$ritit = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__), RecursiveIteratorIterator::CHILD_FIRST);
$r = array();
foreach ($ritit as $splFileInfo) {
$path = $splFileInfo->isDir()
? array($splFileInfo->getFilename() => array())
: array($splFileInfo->getFilename());

for ($depth = $ritit->getDepth() - 1; $depth >= 0; $depth--) {
$path = array($ritit->getSubIterator($depth)->current()->getFilename() => $path);
}
$r = array_merge_recursive($r, $path);
}

print_r($r);

List all the files and folders in a Directory with PHP recursive function

Get all the files and folders in a directory, don't call function when you have . or ...

Your code :

<?php
function getDirContents($dir, &$results = array()) {
$files = scandir($dir);

foreach ($files as $key => $value) {
$path = realpath($dir . DIRECTORY_SEPARATOR . $value);
if (!is_dir($path)) {
$results[] = $path;
} else if ($value != "." && $value != "..") {
getDirContents($path, $results);
$results[] = $path;
}
}

return $results;
}

var_dump(getDirContents('/xampp/htdocs/WORK'));

Output (example) :

array (size=12)
0 => string '/xampp/htdocs/WORK/iframe.html' (length=30)
1 => string '/xampp/htdocs/WORK/index.html' (length=29)
2 => string '/xampp/htdocs/WORK/js' (length=21)
3 => string '/xampp/htdocs/WORK/js/btwn.js' (length=29)
4 => string '/xampp/htdocs/WORK/js/qunit' (length=27)
5 => string '/xampp/htdocs/WORK/js/qunit/qunit.css' (length=37)
6 => string '/xampp/htdocs/WORK/js/qunit/qunit.js' (length=36)
7 => string '/xampp/htdocs/WORK/js/unit-test.js' (length=34)
8 => string '/xampp/htdocs/WORK/xxxxx.js' (length=30)
9 => string '/xampp/htdocs/WORK/plane.png' (length=28)
10 => string '/xampp/htdocs/WORK/qunit.html' (length=29)
11 => string '/xampp/htdocs/WORK/styles.less' (length=30)

Converting Mysql Select to Multidimensional Array of Directory Structure independent of levels using PHP

I ended up solving this by not putting the menu items in a multidimensional array.

The end result I was looking for was to convert the DB query to HTML, so having the parent array and children array, I created a recursive function that concatenates the menu items into an unordered list with tags.

I have tested it with 3 levels deep so far but from what I can see it should not break with deeper levels.

// returns a string value of an HTML built multi-level list ready to display in HTML
// requires 2 arrays. $tree array contains the top parent folders
// and $children array contains all other folders which are not the top parents i.e. all the children
// and grandchildren and so on.
function findChildren($tree, $children){
$message = "";

foreach($tree as $folder){
$parent = array();
if($folder['parentId'] === null) {
$message .= "<li id='" . $folder['folderId'] . "'>" . $folder['folderName'] . " " . $folder['folderId'];
}
$i = 0;
foreach ($children as $child) {
if ($child['parentId'] === $folder['folderId']) {
if (($childKey = array_search($child, $children)) !== false) {
if($i === 0){
$message .= "<ul>";
}
$message .= "<li>" . $child['folderName'] . " " . $child['folderId'];
$parent[$i] = $children[$childKey];
unset($children[$childKey]);
$message .= "</li>";
}
$i++;
}
}
if(isset($parent[0])) {
$message .= findChildren($parent, $children);
}
if($i > 0){
$message .= "</ul>";
}
if($folder['parentId'] === null) {
$message .= "</li>";
}
}
return $message;
}

// Searches through DB for user folders and returns whatever findChildren() returns.
// requires a $userID as int
function getDirTree($userId){
global $mysqli;

$children = array();
$tree = array();

if($folders = $mysqli->prepare("SELECT folders.id, folders.name, child_of_folder.parent_id
FROM child_of_folder
RIGHT JOIN folders
ON (child_of_folder.child_id = Folders.id)
WHERE folders.user_id = ?;")) {
// Bind the parameters... s for String and the variable $name to be bound.
if ($folders->bind_param("i", $userId)) {
// execute the query
if ($folders->execute()) {
// store the results
if($folders->store_result()){
// bind the results
if($folders->bind_result($folderId, $folderName, $parentId)) {
// Fetch the results
while ($folders->fetch()) {
if ($parentId === null) {
array_push($tree, array('folderId' => $folderId, 'folderName' => $folderName, 'parentId' => $parentId));
} else {
array_push($children, array('folderId' => $folderId, 'folderName' => $folderName, 'parentId' => $parentId));
}
}
} else {
$hasFolder = null;
}
} else {
// if there were no values to store return false
$hasFolder = null;
}
} else {
// if there was a problem executing the statement return null
$hasFolder = null;
}
} else {
// if there was a problem binding the statement return null
$hasFolder = null;
}
} else {
// if there was a problem preparing the statement return null
$hasFolder = null;
}
// Call findChildren
$message = findChildren($tree, $children);

// Add the surrounding block elements which would ideally be placed in the template to separate php logic and html
if ($message != ""){
$message = "<ul>" . $message;
$message .= "</ul>";
} else {
$message .= "No Folders Created";
}

$folders->free_result();
$mysqli->close();

return $message;
}

Get the hierarchy of a directory with PHP

function dir_contents_recursive($dir) {
// open handler for the directory
$iter = new DirectoryIterator($dir);

foreach( $iter as $item ) {
// make sure you don't try to access the current dir or the parent
if ($item != '.' && $item != '..') {
if( $item->isDir() ) {
// call the function on the folder
dir_contents_recursive("$dir/$item");
} else {
// print files
echo $dir . "/" .$item->getFilename() . "<br>";
}
}
}
}

Recursively crawl files and directories and return a multidimensional array

I don't think there's any reason the "$allFiles" variable should be static.

Also, you're using a $currentPath variable that isn't defined anywhere. What were you trying to achieve with that variable?

Try this code instead (it probably still isn't perfect, but should give you enough hint on how to make real recursion):

function ftpFileList($ftpConnection, $path="/") {
$files = array();
$contents = ftp_nlist($ftpConnection, $path);
foreach($contents as $currentFile) {
if($currentFile !== "." && $currentFile !== ".."){
if( strpos($currentFile,".") === false || strpos($currentFile,"." === 0) ) {
$files[$path][$currentFile] = ftpFileList($ftpConnection, $path.$currentFile.'/');
}else{
if($currentPath !== "." && $currentPath !== "..")
$files[$path][] = $currentFile;
}
}
}
return $files;
}

How to list files and folder in a dir (PHP)

PHP 5 has the RecursiveDirectoryIterator.

The manual has a basic example:

<?php

$directory = '/system/infomation/';

$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));

while($it->valid()) {

if (!$it->isDot()) {

echo 'SubPathName: ' . $it->getSubPathName() . "\n";
echo 'SubPath: ' . $it->getSubPath() . "\n";
echo 'Key: ' . $it->key() . "\n\n";
}

$it->next();
}

?>

Edit -- Here's a slightly more advanced example (only slightly) which produces output similar to what you want (i.e. folder names then files).

// Create recursive dir iterator which skips dot folders
$dir = new RecursiveDirectoryIterator('./system/information',
FilesystemIterator::SKIP_DOTS);

// Flatten the recursive iterator, folders come before their files
$it = new RecursiveIteratorIterator($dir,
RecursiveIteratorIterator::SELF_FIRST);

// Maximum depth is 1 level deeper than the base folder
$it->setMaxDepth(1);

// Basic loop displaying different messages based on file or folder
foreach ($it as $fileinfo) {
if ($fileinfo->isDir()) {
printf("Folder - %s\n", $fileinfo->getFilename());
} elseif ($fileinfo->isFile()) {
printf("File From %s - %s\n", $it->getSubPath(), $fileinfo->getFilename());
}
}

PHP scandir recursively

You can scan directory recursively in this way the target is your top most directory:

function scanDir($target) {

if(is_dir($target)){

$files = glob( $target . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned

foreach( $files as $file )
{
scanDir( $file );
}

}
}

You can adapt this function for your need easily.
For example if would use this to delete the directory and its content you could do:

function delete_files($target) {

if(is_dir($target)){

$files = glob( $target . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned

foreach( $files as $file )
{
delete_files( $file );
}

rmdir( $target );

} elseif(is_file($target)) {

unlink( $target );
}

You can not do this in the way you are doing.
The following function gets recursively all the directories, sub directories so deep as you want and the content of them:

function assetsMap($source_dir, $directory_depth = 0, $hidden = FALSE)
{
if ($fp = @opendir($source_dir))
{
$filedata = array();
$new_depth = $directory_depth - 1;
$source_dir = rtrim($source_dir, '/').'/';

while (FALSE !== ($file = readdir($fp)))
{
// Remove '.', '..', and hidden files [optional]
if ( ! trim($file, '.') OR ($hidden == FALSE && $file[0] == '.'))
{
continue;
}

if (($directory_depth < 1 OR $new_depth > 0) && @is_dir($source_dir.$file))
{
$filedata[$file] = assetsMap($source_dir.$file.'/', $new_depth, $hidden);
}
else
{
$filedata[] = $file;
}
}

closedir($fp);
return $filedata;
}
echo 'can not open dir';
return FALSE;
}

Pass your path to the function:

$path = 'elements/images/';
$filedata = assetsMap($path, $directory_depth = 5, $hidden = FALSE);

$filedata is than an array with all founded directories and sub directories with their content. This function lets you scan the directories structure ($directory_depth) so deep as you want as well get rid of all the boring hidden files (e.g. '.','..')

All you have to do now is to use the returned array, which is the complete tree structure, to arrange the data in your view as you like.

What you are trying to do is in fact a kind of file manager and as you know there are a lot of those in the wild, open source and free.

I hope this will help you and I wish you a merry Christmas.



Related Topics



Leave a reply



Submit