PHP recursively find files and folders and create HTML - php

Basically what I am trying to do is take a base directory (already defined) and recursively go down it, making a link in a navbar for files and a collapsible for directories; under the collapsible would be links for files in that directory and possibly more collapsibles for directories inside the directory. Here is what I have so far, which is not working:
foreach (new DirectoryIterator($dir) as $file) {
if ($file->isDot()) continue;
if ($file->isFile()) {
echo "<li>" . $file . "</li>"; /*This successfully
creates links named from all the files in the directory specified by $dir */
}
if ($file->isDir()) {
?>
<li class="no-padding">
<ul class="collapsible collapsible-accordion">
<li>
<a class="collapsible-header"><?php echo $file->getFilename(); ?></a>
<div class="collapsible-body">
<ul>
<?php
$dir2 = $file->getFilename();
foreach (new DirectoryIterator($dir."/".$dir2) as $file1) {
if ($file1->isDot()) continue;
if ($file1->isFile()) {
echo "<li>".$file1 . "</li>"; }
} ?>
</ul>
</div>
</li>
</ul>
</li>
<?php
}
}
?>
However, for some reason it seems a DirectoryIterator within a DirectoryIterator is no good (the $dir2 was for test purposes). Or I could have a syntax issue. The reason I want this to work this way is because I want the files to be contained in <li>file</li> html and the files under a directory to be in <li>file-in-folder</li> format.
If there is a better way to do this, please let me know! Thanks!
EDIT: I changed $1file to $file1 and it works fine, even appended the dir; however, I basically want something like a for loop that will keep creating the collapsibles within each other if there is still a directory present. Basically so it would automatically create the formatting if I had:
Dir1 (main) >
File 1 //link
File 2 //link
Dir 1 > //collapsible header
File 1.1 //collapsible button
File 1.2 //...
Dir 2 >
File 2.1
File 2.2
Dir 3
Without me having to write 10 nested DirectoryIterators, just in case you can go down that far.

I think you are using an invalid variable name. PHP accepts variables starting with letters and underscore followed by other chars. Try $file1 instead of $1file
Cheers!
http://php.net/manual/en/language.variables.basics.php

This is my logic, probably you can get some idea from here.
if your main folder looks like this
then here is the code to get the folder structures.
echo '<pre>';
$dir='folders';
$files = array_slice(scandir($dir), 2);
foreach($files as $k=>$file){
$dir1=$dir.'/'.$file;
if(is_dir($dir1)){
$files1 = array_slice(scandir($dir1), 2);
if(!$files1){
$FOLDERS[$file]=$file;
}else{
foreach($files1 as $kk=>$file1){
$dir2=$dir1.'/'.$file1;
$files2 = array_slice(scandir($dir2), 2);
if(!$files2){
$FOLDERS[$file][$file1]=$file1;
}else{
foreach($files2 as $file2){
$FOLDERS[$file][$file1][$file2]=$file2;
}
}
}
}
}
}
print_r($FOLDERS);
Output:
Array
(
[folder1] => folder1
[folder2] => Array
(
[folder3] => Array
(
[folder4] => folder4
)
[folder5] => folder5
[folder6] => folder6
)
)
i used it only to scan the folders, you can extend it according to your needs.

Related

PHP Create Image Gallery From Directory And Subdirectories

I'm trying to make an image gallery that scans a main directory and creates a separate album for each subdirectory.
My structure is similar to this:
-Gallery
--Subdir 1
---Image 1
---Image 2
--Subdir 2
---Image 1
---Image 2
The idea is that each album is going to be made of a div with a class of web-gallery. Then there will be a header for the album title made from the subdirectories name. After that a list is generated of each image. This is going to be a one page gallery. If possible I would like to have a variable that sets how many albums are listed that way if I have 30 subdirectories my page doesn't get too crowded.
So far I've written this but it doesn't work. I'm not getting any errors or logs though it just doesn't work.
$dirs = glob('img/gallery_temp/*', GLOB_ONLYDIR);
foreach($dirs as $val) {
echo '<div class="web-gallery">';
echo "<h3><span>ยป</span> ".basename($val). "</h3>";
echo '<ul class="web-gallery-list">';
$files = glob($val.'*.{jpg,png,gif}', GLOB_BRACE);
foreach($files as $file) {
echo "<li><a href='".$file."'><img src='" . $file . "' alt='description'></a></li> \r\n";
}
echo "</ul>";
echo "</div>";
}
Simply add a / before *.{jpg,png,gif} like this:
$files = glob($val.'/*.{jpg,png,gif}', GLOB_BRACE);
This is because $val doesn't have a final / for the directory.
You might consider using "readdir" instead of glob. Glob is to find pathnames matching a pattern, see here: http://php.net/manual/en/function.glob.php and is known to be a bit problematic.
Readdir, if your directory is entirely images might be easier to use: http://php.net/manual/en/function.readdir.php
Couple this with is_dir() http://php.net/manual/en/function.is-dir.php to resolve your directories vs files. Here is a snippet
<?php
if ($handle = opendir('/galleries')) {
while (false !== ($entry = readdir($handle))) {
// this is a subdirectory
if (is_dir($entry)) {
}
// this is a file
else {
echo $entry;
}
}
closedir($handle);
}
?>
If you make it a recursive function you could actually have it traverse a number of subdirectories creating galleries within galleries.
I also found this fantastic little snippet that is very elegant on another stack question: Get Images In Directory and Subdirectory With Glob
$rdi = new RecursiveDirectoryIterator("uploads/prevImgs/");
$it = new RecursiveIteratorIterator($rdi);
foreach($it as $oneThing)
if (is_file($oneThing))
echo '<img src="'.$oneThing.'" /><br />';
Using SPL Library (PHP >= 5)
Better solution in your case
is to use SPL library (the most cross-platform)
$directory = new RecursiveDirectoryIterator("./img/gallery_temp", FilesystemIterator::SKIP_DOTS);
// Flatten the recursive iterator, folders come before their files
$it = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
foreach($it as $fileinfo)
{
if($fileinfo->isDir())
{
// prevPath used to separate each directory listing and closing the bracket UL list
$prevPath = $it->getSubPath().DIRECTORY_SEPARATOR.$fileinfo->getFilename();
echo sprintf
(
"<div class='web-gallery'>
<h3><span>></span> %s</h3>
<ul>".PHP_EOL,
$fileinfo->getFilename()
);
}
if($fileinfo->isFile())
{
echo sprintf("<li><a href=''><img src='%s/%s' alt='description'></a></li>".PHP_EOL, $it->getSubPath(), $fileinfo->getFilename());
if($prevPath != $it->getSubPath())
echo("</ul>");
}
}
Note:
For more informations : SPL Documentation
DIRECTORY_SEPARATOR is a cross-platform constant, will use the
correct directory separator of the OS where are executed the code
FilesystemIterator::SKIP_DOTS, avoid to fetch the '.' and '..' dir
link level.
you can limit the depth of scanning with $it->setMaxDepth(5);

How to scan directories within directories in a PHP loop

$dirs = scandir("../public_html/");
$subDirArr=array();
foreach ($dirs as $currentIndex => $currentDir) {
if (is_dir($currentDir))
if (!($currentDir[0] == "."))
echo "<a href='../public_html/$currentDir'>$currentDir</a><br/>";
}
So I've got this code that scans my public_html directory on my server and echos out all the subdirectories (but not the files) so that I have a list of clickable links to my subdirectories.
What I want to do is when one of the directories is clicked, have it show IT'S subdirectories (if any). I can't figure out how to logically do that though. I could write a loop within a loop within a loop, etc, but I want this code to work no matter how many directories I add.
How could I accomplish this?
The endgoal is to have a menu system for my hosting files/folders.
Something like this should do the trick. You can adjust function to whatever needed:
function getDirs($root)
{
foreach (scandir($root) as $dir) {
if ( ! in_array($dir, ['.', '..'])) {
$path = realpath($root . DIRECTORY_SEPARATOR . $dir);
if (is_dir($path)) {
echo $path . PHP_EOL;
getDirs($path);
}
}
}
}
getDirs("../public_html/");

PHP - Scan dir for folders and txt

I am dynamically building an accordion menu. Accordion will get the header information from folder names and contents from .txt files associated to folder names. They are relatives in terms of directory.
<div class="accordion">
<?php if($_GET['cat']!='') {
$handleCat = 'tv/'.$_GET['cat'];
$category = scandir($handleCat);
$i = 1;
foreach ($category as &$value) {if ((!in_array($value,array(".","..","...")))){
echo '<div class="header">'.$value.'</div><div class="content" id="ac'.$i.'">'.file_get_contents($value.".txt", false).'</div>';
$i+=1;}}}
?>
</div>
In my code there are two problems. First one is logic problem. I couldn't made up scan foldernames and file names seperately. Forexample program1.txt also becomes a headername. Second problem is method problem. I found file_get_contents() method but this doesn't extracts .txt file contents.
You can distinguish files from folders using the function is_dir().
As of file_get_contents, it reads the file contents but does not echo it. Use :
echo '<div class="header">'.$value.'</div>'.$value.'<div class="content" id="ac'.$i.'">';
echo file_get_contents($value.".txt", false);
echo'</div>';
Use the following to list files in a directory. Where I commented code you can do whatever you want with that particular file. You can use is_dir() to distinguish from files and directories and then proceed accordingly.
<?php
if ($dir = opendir('.')) {
while (false !== ($file = readdir($dir))) {
if ($file != "." && $file != "..") {
echo "$file\n";
//code
}
}
closedir($handle);
}
?>
Read the contents of a file using the following code.
$contents = file_get_contents($file);

PHP to post links to sub directories & php to display images

I'm very basic when it comes to PHP.
With my website, I have a directory called "uploads"
Within "uploads" I have 3 folders "Example1" "Example2" and "Example3"
Within each of the folders, they contain images.
I need to know how to use php to create a navigation for every sub directory.
So that if I add a new folder "Example4" it will give a navigation like:
Select what section you're looking for:
Example1 | Example2 | Example3
and if I later add new folders add them to the navigation.
EX:
Example1 | Example2 | Example3 | Example4 | Example5
Then once they click the link to go into the folder, have a code that displays all the images in that folder.
So far I have:
<?php
$files = glob("uploads/*.*");
for ($i=0; $i<count($files); $i++)
{
$num = $files[$i];
echo '<img src="/'.$num.'">'."<p>";
}
?>
but it will only display the images in the upload directory, not the images in Example1 and so on.
How on earth would I go about doing this? I'm doing it for a school project and have two weeks to complete it, but I am so lost. I only have knowledge with CSS, HTML, and the only PHP I know is php includes, so any help would be appreciated.
Since it seems that you are familiar with globs a bit, here is an example using the "glob" function. You can see a basic working example of what you are looking for here:
http://newwebinnovations.com/glob-images/
Here is how I have the example set up:
There are two PHP files, one is index.php and the other is list-images.php.
There is also a folder for images two subfolders that have images inside of them.
index.php is the file that finds the folders in the images folder and places them in a list with links list-images.php which will display the images inside of the folder:
$path = 'images';
$folders = glob($path.'/*');
echo '<ul>';
foreach ($folders as $folder) {
echo '<li>'.$folder.'</li>';
}
echo '</ul>';
The links created above have a dynamic variable created that will pass in the link to the list-images.php page.
Here is the list-images.php code:
if (isset($_GET['folder'])) {
$folder = $_GET['folder'];
}
$singleImages = array();
foreach (glob($folder . '/*.{jpg,jpeg,png,gif}', GLOB_BRACE) as $image) {
$imageElements = array();
$imageElements['source'] = $image;
$singleImages[$image] = $imageElements;
}
echo '<ul>';
foreach ($singleImages as $image) {
echo '<li><img src="'.$image['source'].'" width="400" height="auto"></li>';
}
echo '</ul>';
The links created here will link you to the individual images.
To get files of every specific folder ,pass it throw a get variable that contains folder's name,an then scan this folder an show images ,url should be like this :
listImages.php?folderName=example1
To have menu like what you want :
<?php
$path = 'uploads/' ;
$results = scandir($path);
for ($i=0;$i<count($results);$i++ ) {
$result=$results[$i];
if ($result === '.' or $result === '..') continue;
if (is_dir($path . '/' . $result)) {
echo "<a href='imgs.php?folderName=$result'>$result</a> ";
}
if($i!=count($results)-1) echo '|'; //to avoid showing | in the last element
}
?>
And here is PHP page listImages that scan images of a specific folder :
<?php
if (isset($_GET['folderName'])) $folder=$_GET['folderName'];
$path = 'uploads/'.$folder.'/' ;
$images = glob($path . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
foreach ($images as $image) {
echo "<img src='$image' />";
}
?>
First of all, do read more PHP manual, for directory related: opendir, for files related: fopen
The following code is basically re-arranging the example code provided in opendir. What it does:
A scan_directory function to simply check if directory path is valid and is a directory, then proceed to do a recursive call if there's a child directory else just print out the file name.
The first if/else condition is just to ensure the base directory is valid.
I'll added ul and li to make it slightly more presentable.
$base_dir = 'upload';
if (is_dir($base_dir))
scan_directory($base_dir);
else
echo 'Invalid base directory. Please check your setting.';
// recursive function to check all dir
function scan_directory($path) {
if (is_dir($path)) {
if ($dir_handle = opendir($path)) {
echo '<ul>';
while (($file = readdir($dir_handle)) !== false) {
if ($file != '.' && $file != '..') {
if (is_dir($path . '/' . $file)) {
echo '<li>';
echo $file;
scan_directory($path . '/' . $file);
echo '</li>';
}
else
echo "<li>{$file}</li>";
}
}
echo '</ul>';
}
}
}
create image as subdirectory name with image name and save it in database
example:
subdirectory name: example2
image name: image.jpg
store image name in db as "example2/image.jpg"

PHP to build gallery navigation

I was wondering if it is possible to use my server's file structure to automatically build a navigation menu for an image gallery.
Currently I have a simple "showcase" with hard-coded links to different folders of images (using jquery and ajax and php, some things that I don't quite understand but learned how to use from tutorials and the like). Basically, I have three files:
main.php
main.css
images.php
and I use hard links on main.php to call the images.php script to load a specific folder containing images into a div on the main page.
Here is my current nav setup:
<ul>
<li>Animals</li>
<li>People</li>
<li>Objects</li>
</ul>
My question is: Since all my images are in subdirs under the "images" dir, is there a way I can just build the navigation points (php script?) using the names of the subdirs in "images"? (such that it is kept up to date when I add more folders)
also, for some reason I can't make the variables on my script include the 'images.php?dirname=images/', is there any way to fix that?
If they are all in the images directory, you can specify a $image_path
<?php
$image_path = '/full/path/to/images';
if ($_GET['gallery']) {
$gallery_path = $image_path . '/' . $_GET['gallery'];
# if $_GET['gallery'] is `animals`:
#
# $gallery_path = '/full/path/to/images/animals'
# load your images within this path
}
?>
And to get all the subdirectories use dir
<?php
$image_path = '/full/path/to/images';
$d = dir($image_path);
while (false !== ($entry = $d->read())) {
if (is_dir($image_path . $entry)) {
if (($entry != '.') || ($entry != '..')) {
echo $entry; # or print your html code for each directory.
}
}
}
?>

Categories