Reputation: 35
I'm having an an issue trying to merge a few arrays together for a project I'm working on. I'm getting closer to the desired results and I've searched this site and can't find a working solution.
I doubt it matters, but this project is being tested on IIS but the end result has to work on both IIS and Apache.
So here goes... I have four directories that I need to merge and sort alphabetical.
$dir1 = "D:\\dir1";
$dir2 = "D:\\dir2";
$dir3 = "D:\\dir3";
$dir4 = "D:\\dir4";
$dirA = array($dir1,$dir2,$dir3,$dir4);
If I do the following I'm getting 'close' to the results I need:
try
{
$object = new ArrayIterator($dirA);
foreach($object as $key=>$value)
{
foreach(new DirectoryIterator($value) as $item)
{
if(!$item->isDot())
{
echo $item->getFilename() .' ';
if(file_exists($value.'\\'.$item.'\folder.jpg'))
{
echo 'Y<br />';
} else {
echo 'X<br />';
}
}
}
}
}
catch(Exception $e)
{
echo $e->getMessage();
}
and end up with a list of folders from each directory (in alphabetical order) but they don't merge, instead it still groups them by $item->key()
(which I guess is what I'm actually trying to merge? I have tried numerous ways of using array_merge
with no success)
I've tried using sort
and ksort
, etc. but either they wont work or I can't figure out the correct placement of it to work before I echo
the list.
My end goal is to echo
this entire thing into a table where I use multiple file_exists
to check for specific files that 'should' be available in every one of the folders... for example, each should have a 'folder.jpg' in it's root, so I'd want it to show something like:
Folder Name folder.jpg (other files to be verify)
Directory1 Y Y Y Y Y Y
Directory2 Y Y X Y Y Y
Directory3 X X Y X X X
Directory4 Y Y Y Y Y Y
--
Hopefully the above isn't confusing and provides enough information, I want to thank anyone who is able to help and offer an invite to anyone who would be willing to help out with the project to contact me (I'll obviously credit the person on the corresponding areas).
Thanks again.
--
Edit: Trying to clarify a bit.
In the end, this project will write certain variables to a 'settings.ini' and read those (I have that part working fine, so I'm ignoring that altogether right now and writing everything locally in a single file).
In my case, I have 4 folders on different drives, each folder has between 15 and 130 sub-directories (all unique names). So an abbreviated list would look similar to:
T:\New Set\
A\
D\
G\
D:\Old Set\
B\
F\
etc.
---------
$dir1 = 'T:/New Set';
$dir2 = 'D:/Old Set';
$dir3 = 'D:/Overage';
$dir4 = 'G:/Unsorted';
$dirA = array($dir1,$dir2,$dir3,$dir4);
Using the code I originally posted above would give me something like below (instead of them alphabetical)
A // from $dir1
D // from $dir1
G // from $dir1
B // from $dir2
F // from $dir2
etc.
Using the code posted by DaveRandom, it displayed the following:
Array ( [T:\New Set] => Array ( [folder.jpg] => 1 [cover.jpg] => [poster.jpg] => ) [D:\Old Set] => Array ( [folder.jpg] => 1 [cover.jpg] => [poster.jpg] => ) [D:\Overage] => Array ( [folder.jpg] => 1 [cover.jpg] => [poster.jpg] => ) [G:\Unsorted] => Array ( [folder.jpg] => 1 [cover.jpg] => [poster.jpg] => ) )
Folder Name folder.jpg cover.jpg poster.jpg
T:\New Set Y X X
D:\Old Set Y X X
D:\Overage Y X X
G:\Unsorted Y X X
I guess for now, the only question I have is solely sorting the sub-directories since I'm able to verify the files and do the table in other ways. So to make it clear, I want the directory array to not display like above, but like the below instead:
A // from $dir1
B // from $dir2
D // from $dir1
F // from $dir2
G // from $dir1
etc.
Upvotes: 1
Views: 453
Reputation: 88697
I'm a little confused by your question, but I think that for what you are trying to do you would be best to build a table-like data structure in a 2D array, which you can then iterate over afterwards to display as a table. You could do it all in one go, but it will make you code a lot more readable/maintainable to separate the data acquisition and display generation logic.
I also think you have massively over complicated this in you own head with the directory iterator. All you are really trying to do (based on your example output) is check for the existence of certain files at the top level of a list of directories - in which case all you need to do is iterate the list of directories, then iterate the list of files you are looking for.
I also really don't see the point in the ArrayObject/ArrayIterator here because you are not modifying the array you are working with. You can just loop the array itself.
Like so:
EDITED to reflect comments. The sorting magic you need here comes courtesy of array_multisort()
.
// Don't forget to escape \ backslashes!
// Also, / works on Windows too...
$dirA = array(
"D:\\dir1",
"D:\\dir2",
"D:\\dir3",
"D:\\dir4"
);
// The list of files you are checking for
$files = array(
'folder.jpg',
'cover.jpg',
'poster.jpg'
);
// The "columns" we want to sort by (highest priority first)
// This is equivalent to SQL: ORDER BY name ASC, path ASC
$sortCols = array(
'name' => SORT_ASC,
'path' => SORT_ASC
);
// This will be our results "table"
$results = array();
// This will hold the sort column items
$sortInfo = array();
foreach ($sortCols as $colName => $flags) {
$sortInfo[$colName] = array();
}
// Loop parent directories
foreach ($dirA as $dir) {
// Make a DirectoryIterator and loop it
foreach (new DirectoryIterator($dir) as $child) {
// Skip files and parent dir
if (!$child->isDir() || $child->isDot()) {
continue;
}
// Temp array to hold data about this sub-dir
$result = array();
$result['path'] = $child->getPathname();
$result['name'] = basename($result['path']);
// Now check for the existence of files in the file list
// You might want to use is_file() instead of file_exists() since
// it is possible for there to be a directory named 'folder.jpg'
foreach ($files as $file) {
$result[$file] = file_exists($result['path'].'\\'.$file);
}
// Create a "row" for this sub-directory
$results[] = $result;
// Create sort data for this directory
foreach ($sortCols as $colName => $flags) {
$sortInfo[$colName][] = $result[$colName];
}
} // foreach DirectoryIterator
} // foreach $dirA
// Now we have an array of "rows" corresponding to each sub-directory
// we can do some sorting magic with it.
// First we prepare the data to pass to array_multisort() as an array
// of arguments, which we can use with call_user_func_array(). This
// approach allows a dynamic number of sort columns.
$sortData = array();
foreach ($sortCols as $colName => $flags) {
$sortData[] = $sortInfo[$colName];
$sortData[] = $flags;
}
$sortData[] = &$results; // Last arg is passed by reference!
// Now we call it
call_user_func_array('array_multisort', $sortData);
// Now we output a table
echo "<table>\n";
// Header row
echo "<tr><th>Folder Name</th><th>Full Path</th>";
foreach ($files as $file) {
echo "<th>$file</th>";
}
echo "</tr>\n";
// Data rows
foreach ($results as $row) {
echo "<tr><td>{$row['name']}</td><td>{$row['path']}</td>";
foreach ($files as $file) {
echo $row[$file] ? "<td>Y</td>" : "<td>X</td>";
}
echo "</tr>\n";
}
echo "</table>";
Upvotes: 1