I'm at my wit's end here trying to generate a list of all directories and files in PHP. The idea was so that the navigation bar could be dynamically updated simply by adding more files.
An example of what the directory structure might look like is as follows:
- Directory 1
- Subdirectory 1
- Category 1
- Page 1
- Page 2
- Category 2
- ...
- Category 1
- Subdirectory 1
- Directory 2
- Subdirectory...
- Directory 3
- ...
Each page would be linked to. For example, Directory 1 -> Subdirectory 1 -> Category 1 -> Page 1 would be /directory-1/subdirectory-1/category-1/page-1
.
I found a few potential solutions but none that really fitted the bill. I chose to build off of this comment on the PHP website.
This is my code (first function is lifted directly from that linked comment):
function dirToArray($dir) {
$result = array();
$cdir = scandir($dir);
foreach ($cdir as $key => $value)
{
if (!in_array($value,array(".","..")))
{
if (is_dir($dir . DIRECTORY_SEPARATOR . $value))
{
$result[$value] = dirToArray($dir . DIRECTORY_SEPARATOR . $value);
}
else
{
$result[] = $value;
}
}
}
return $result;
}
$contentsArray = dirToArray("contents");
function listStuff($contentsArray, $contentsArrayArray, $parentDirectory) {
foreach ($contentsArrayArray as $key => $value) {
if (is_array($value)) {
if (!empty($GLOBALS["depthWorkaround"])) {
$parentDirectory = $GLOBALS["depthWorkaround"];
$GLOBALS["depthWorkaround"] = null;
}
$isDirectory = true;
$directoryName = explode("_", $key)[1];
$directoryURL = str_replace(" ", "-", strtolower($directoryName));
echo "<li> <a href=\"$parentDirectory/$directoryURL\">$directoryName</a></li>";
if (!empty($contentsArrayArray[$key])) {
$parentDirectory = "$parentDirectory/" . $directoryURL;
echo "<ul>";
listStuff($contentsArray, $contentsArrayArray[$key], $parentDirectory);
echo "</ul>";
}
} else {
$isDirectory = false;
$directoryName = explode("_", $value)[1];
$directoryURL = str_replace(" ", "-", strtolower($directoryName));
echo "<li> <a href=\"$parentDirectory/$directoryURL\">$directoryName</a></li>";
}
}
$GLOBALS["depthWorkaround"] = explode("/", $parentDirectory)[1];
}
listStuff($contentsArray, $contentsArray, null);
I think it's best I try and explain what is going on here. The dirToArray
function lists everything in a directory as a multidimensional array. It's really rather neat. In this case, my chosen directory is "contents".
Next up is listStuff
. It does a number of things, mostly turning the array into a list, similar to shown above, and making them all hyperlinks, with the URLs being lowercase and no spaces.
If you are testing this yourself, note that all directories and files must have an underscore in them, or things will go wrong. This is because it's designed to have them listed like "00_File 1", "01_File 2" and so on to keep the items in the intended order. The numbers are then stripped from the resulting output, but I haven't done anything to make it handle the lack of an underscore yet, as it would be nice to get the essential parts working first, and it is only for personal use.
The issue is that I haven't been able to get the resulting URLs quite right. Here's an example of what it produces:
- Directory:
/directory
- Subdirectory:
/directory/subdirectory
- Subsubdirectory 1:
/directory/subdirectory/subsubdirectory-1
- File:
/directory/subdirectory/subsubdirectory/file
- File:
- Subsubdirectory 2:
/directory/subsubdirectory-2
- File:
/directory/subsubdirectory/file
- File:
- Subsubdirectory 3:
/directory/subsubdirectory-3
- File:
/directory/subsubdirectory-3/file
- File:
- File:
/directory/subdirectory/subsubdirectory/file
- Subsubdirectory 1:
- File:
/directory/subdirectory/file
- Subdirectory:
As you might be able to see, the URLs are completely out of whack, often pointing to an incorrect directory and one level deeper than they should after going up a level (or multiple levels).
I'm really not sure where to go from here to try and get out of this mess. Whatever I try either does not result in a successful recursive directory listing, or getting the appropriate hyperlinks in place is impossible.