Learning PHP. Have recursive directory loop issue - php

So, I'm familiar with Javascript, HTML, and Python. I have never learned PHP, and at the moment, I'm banging my head against my desk trying to figure out what (to me) seems to be such a simple thing.
I have a folder, with other folders, that contain images.
At the moment, I'm literally just trying to get a list of the folders as links. I get kind of there, but then my output is always reversed! Folder01, Folder02 comes out as Folder02, Folder01. I can't fricken' sort my output. I've been searching constantly trying to figure this out but nothing is working for me.
<?php
function listAlbums(){
if ($handle = opendir('./photos/')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo $entry . "<br/>";
}
}
closedir($handle);
}
}
?>
This outputs: Folder02, Folder01. I need it the other way around. I've tried asort, array_reverse, etc. but I must not be using them properly. This is killing me. I never had to even thin about this in Python, or Javascript, unless I actually wanted to have an ascending list...

Try one of these, one is recursive, one is not:
// Recursive
function listAlbums($path = './photos/')
{
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
foreach($objects as $name => $object) {
ob_start();
echo rtrim($object,".");
$data = ob_get_contents();
ob_end_clean();
$arr[] = $data;
}
return array_unique($arr);
}
// Non-recursive
function getAlbums($path = './photos/')
{
$objects = dir($path);
while (false !== ($entry = $objects->read())) {
if($entry !== '.' && $entry !== '..')
$arr[] = $path.$entry;
}
$objects->close();
return $arr;
}
// I would use __DIR__, but not necessary
$arr = listAlbums();
$arr2 = getAlbums();
// Reverse arrays by key
krsort($arr);
krsort($arr2);
// Show arrays
print_r($arr);
print_r($arr2);

I try your code and make simple changes and I am able to do what you want to get.
Here is my code ( copy of your code + Modify ) :
function listAlbums() {
$files = array();
if ($handle = opendir('./photos/')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
//echo $entry . "<br/>";
$files[] = $entry;
}
}
closedir($handle);
}
// Sort your folder in ascending order
sort($files);
// Sort your folder in descending order [ code commented ]
//rsort($files);
// Check your photos folder has folder or not
if( !empty( $files ) ) {
// Show Your Folders
foreach ($files as $key => $folderName ) {
echo $folderName . "<br/>";
}
} else {
echo 'You have no folder yet in photos directory';
}
}
My Changes:
First store your all folders in the photos directory in an array variable
Secondly sort this array whatever order you want.
Finally show your folders (And your work will be solved)
You can know more about this from sort-and-display-directory-list-alphabetically-using-opendir-in-php
Thanks

Ok, this is the best result i've gotten all night. This does 99% of what I need. But I still can't figure out this damn sort issue. This code will go through a list of directories, and create lightbox galleries out of the images in each folder. However, the first image is always the last one in the array, and I can't figure out how the heck to get it to sort normally! Check line 16 to see where I talking about.
<?php
function listAlbums(){
$directory = "./photos/";
//get all folders in specified directory
$folders = glob($directory . "*");
//get each folder item name
foreach($folders as $folderItem){
//check to see if the folderItem is a folder/directory
if(is_dir($folderItem)){
$count = 0;
foreach (new DirectoryIterator($folderItem) as $fileInfo) {
if($fileInfo->isDot()) continue;
$files = $folderItem."/".$fileInfo->getFilename();
if ($count == 0){ //This is where my issues start. This file ends up being the last one in the list. I need it to be the first.
echo ''.basename($folderItem).'' . "<br/>";
echo "<div style='display: none'>" . "<br/>";
$count++;
}else{
echo ''.basename($folderItem).'' . "<br/>";
}
}echo "</div>";
}
}
}
?>

Whew! Ok, I got everything working. DirectoryIterator was pissing me off with its random print order. So I fell back to just glob and scandir. Those seem to print out a list "logically". To summarize, this bit of php will grab folders of images and turn each folder into its own lightbox gallery. Each gallery shows up as a hyperlink that triggers the lightbox gallery. I'm pretty happy with it!
So here's my final code:
<?php
function listAlbums(){
$directory = "./photos/";
//get all folders in specified directory
$folders = glob($directory . "*");
//get each folder item name
foreach($folders as $folderItem){
//check to see if the folderItem is a folder/directory
if(is_dir($folderItem)){
$count = 0;
$scanDir = scandir($folderItem);
foreach($scanDir as $file){
if ($file === '.' || $file === '..') continue;
$filePath = $folderItem."/".$file;
if ($count == 0){
echo ''.basename($folderItem).'' . "<br/>";
echo "<div style='display: none'>" . "<br/>";
$count++;
}else{
echo ''.basename($folderItem).'' . "<br/>";
}
}echo "</div>";
}
}
}
Special thanks to Rasclatt for bearing with me through all of this and offering up a lot of hand-holding and help. I really appreciate it!

Related

Need php to load files from folders and subfolders, and then sort the results added to a array

I need to search into folders and subfolders in search for files. In this search I need to know the files names and their path, because I have different folders and files inside of those.
I have this name 05-Navy, and inside this folder I have 3 files called 05_Navy_White_BaseColor.jpg, 05_Navy_White_Normal.jpg and 05_Navy_White_OcclusionRoughnessMetallic.jpg.
I need to only get one of them at a time because I need to add they separately to different lists.
Then I came up with the code below:
function getDirContents($dir, &$results = array()) {
$files = scandir($dir);
$findme = '_BaseColor';
$mypathCordas = null;
$findmeCordas = 'Cordas';
foreach ($files as $key => $value) {
$path = realpath($dir . DIRECTORY_SEPARATOR . $value);
$mypathCordas = $path;
$pos = strpos($mypathCordas, $findme);
$posCordas = strpos($mypathCordas, $findmeCordas);
if (!is_dir($path)) {
if($posCordas == true){
if($pos == true){
$results[] = $path;
}
}
}
else if ($value != "." && $value != ".." ) {
if($posCordas == true){
echo "</br>";
getDirContents($path, $results);
//$results[] = $path;
}
}
}
sort( $results );
for($i = 0; $i < count($results); $i++){
echo $results[$i];
echo "</br>";
}
return $results;
}
getDirContents('scenes/Texturas');
as output result I get this: Results1
Which is not ideal at all, the biggest problem is that the list inserts the same values every time it has do add new ones, and as you can see, it doesn't sort one bit, but it shuffles. I did other things, like I have tried to use DirectoryIterator which worked really well, but I couldn't sort at all...
The printing each time something new is on the list might be my for(), but I am relatively new to php, so I can't be sure.
Also, there's this thing where it gets all the path, and I already tried using other methods but got only errors, where I would only need the scenes/texturas/ instead of the absolute path....

PHP - get single file based on user

I'm having trouble getting my code to work the way I want.
I'm using scandir to get all files from the directory. This gives me a list with pdf files linked to a product, but the problems comes with the posibllity of pdf files multiple languages. Like so:
1096_EN.pdf
867_PT.pdf
914_EN.pdf
914_NL.pdf
Before _ is ID and after language. And I want the user to only see one file per product.
my code looks likes this:
$files = scandir($dir);
foreach ($files as $file)
{
$exp_file = explode("_", $file);
// check file for given ID
if($exp_file[0] == $_GET['iD']){
// check file for userlanguage
if($exp_file[1] == $lang){
echo $file;
}
// check file in english
elseif($exp_file[1] == "EN"){
echo $file;
}
// return available file in other language
else{
echo $file;
}
}
}
In case of 914 and NL the code returns two files. In case of 914 and PT i only get 1 file, 914_EN.pdf and in case of 867 and NL there will be zero files.
What is the best way to filter my files and return the best matched file? I personally think the error is in the for loop, but I cant find a proper way out..
thanks
If you want to have just the single items, you should keep a backlog of which you have already processed, as the foreach loop will go from for example 914_EN.pdf to 914_NL.pdf, while the checks have already been completed for 914_EN.pdf, so when you get to 914_NL.pdf, it just reruns the checks and thinks it is okay.
if working with multiple same values, you can first cleanse the array to get what you wanted. You can take a look at this, if this what you want. Cheers!
$files = array("1096_EN.pdf", "867_PT.pdf", "914_EN.pdf", "914_NL.pdf");
$new_exp_file = array();
foreach ($files as $file) {
$exp_file = explode("_", $file);
$new_exp_file[] = $exp_file[0];
}
$new_exp_file_arr_ = array_values(array_unique($new_exp_file));
for($i = 0, $file_ctr = count($new_exp_file_arr_); $i < $file_ctr; $i++) {
if($new_exp_file_arr_[$i] == "914") {
echo $new_exp_file_arr_[$i] . "<br>";
echo "<ul>";
foreach ($files as $file) {
$exp_file = explode("_", $file);
if($new_exp_file_arr_[$i] == $exp_file[0]) {
echo "<li>" . $exp_file[1] . "</li>";
}
}
echo "</ul>";
}
}
this seems to work for me? Using a regex probably not as efficient as the above methods though.
$_GET['iD'] = 1096;
$ptn = "^((\d+)\_([a-zA-Z]+)\.([a-zA-Z]+))^";
$aFiles = array('1096_EN.pdf','867_PT.pdf','914_EN.pdf','914_NL.pdf');
$lang = "EN";
foreach ($aFiles as $sFileName)
{
preg_match($ptn, $sFileName, $aFileParts);
var_dump($aFileParts);
// check file for given ID
if($aFileParts[2] == $_GET['iD']){
// check file for userlanguage
if(strtolower($aFileParts[3]) == strtolower($lang)){
echo $sFileName;
break;
}
// return available file in other language
else{
echo $sFileName;
}
}
}
I've solved my problem by the following:
if(glob($_GET['iD']."_".$_GET['t']."*.pdf"))
{
$file = glob($_GET['iD']."_".$_GET['t']."*.pdf");
echo $file[0];
}
else
{
if(glob($_GET['iD']."_EN*.pdf"))
{
$file = glob($_GET['iD']."_EN*.pdf");
echo $file[0];
}
else
{
$file = glob($_GET['iD']."*.pdf");
echo $file[0];
}
}
No more looping, just checking for different files with wildcards. Works like a charm. I.m.o. much cleaner with larger lists of files..

readdir() includes an empty folder

I have this part of script that echos the folders in "albums" folder and arrange them by the alphabet, but for some reason it also includes an empty folder.
$directory = opendir("albums/");
$items = array();
while($items[] = readdir($directory))
sort($items);
closedir($directory);
foreach ($items as $item)
{
if(($item != ".") && ($item != "..")){
$files[] = $item;
}
}
What should I do? I think the if(($item != ".") && ($item != "..")) is part of my problem but I can't figure how to handle it.
The problem is with this line:
while($items[] = readdir($directory))
readdir returns false if no entries are left. That is why you have an extra item in $items
EDIT
while($item = readdir($directory))
{
$items[] = $item;
sort($items);
}
. is the current directory and .. is the parent directory. It's normal that readdir() returns these.
BTW you could simplify your code by using the glob() function:
$files = glob("albums/*");
// that's all
glob("albums/*") will return all entries in the albums directory, sorted alphabetically, and without the dot and dotdot entries.
Try this, as it's in sorted order, just array_shift() twice will do this work. But personally I think it's a kinda hacking...
<?php
$files = array();
foreach (glob('album/*') as $file) {
if (!is_dir($file)) {
$files[] = basename($file);
}
}
sort($files);
You can modify 'album/*' to suit your needs (ex. 'album/*.mp3'). Note that this method is not recursive, so if you need to process subdirectories within the album/ directory, you'll want to modify the code to account for this.

PHP Array Blocklist

I've created this code to cycle through the folders in the current directory and echo out a link to the folder, it all works fine. How would I go about using the $blacklist array as an array to hold the directory names of directories I dont want to show?
$blacklist = array('dropdown');
$results = array();
$dir = opendir("./");
while($file = readdir($dir)) {
if($file != "." && $file != "..") {
$results[] = $file;
}
}
closedir($dir);
foreach($results as $file) {
if($blocked != true) {
$fileUrl = $file;
$fileExplodedName = explode("_", $file);
$fileName = "";
$fileNameCount = count($fileExplodedName);
echo "<a href='".$fileUrl."'>";
$i = 1;
foreach($fileExplodedName as $name) {
$fileName .= $name." ";
}
echo trim($fileName);
echo "</a><br/>";
}
}
array_diff is the best tool for this job -- it's the shortest to write, very clear to read, and I would expect also the fastest.
$filesToShow = array_diff($results, $blacklist);
foreach($filesToShow as $file) {
// display the file
}
Use in_array for this.
$blocked = in_array($file, $blacklist);
Note that this is rather expensive. The runtime complexity of in_array is O(n) so don't make a large blacklist. This is actually faster, but with more "clumsy" code:
$blacklist = array('dropdown' => true);
/* ... */
$blocked = isset($blacklist[$file]);
The runtime complexity of the block check is then reduced to O(1) since the array (hashmap) is constant time on key lookup.

Dynamically pulling images and creating links

Is there a way to pull images from a directory and place them on a webpage and have links attached to those images that would take a person to a specific webpage associated with that image using PHP?
Thanks
something like this should do it :
if ($handle = opendir('/path/to/files')) {
    echo "Directory handle: $handle\n";
    echo "Files:\n";
    /* This is the correct way to loop over the directory. */
    while (false !== ($file = readdir($handle))) {
if(substr($file, -3) == 'jpg'){ //modify to handle filetypes you want
        echo "<a href='/path/to/files/".$file."'>".$file."</a>";
}
    }
    closedir($handle);
}
are you asking how to scan the directory or how to associate a list of images with urls?
the answer to the first question is glob() function
the second answer is to use an assoc array
$list = array('foo.gif' => 'bar.php', 'blah.gif' => 'quux.php');
and a foreach loop to output images and links
foreach($list as $src => $href) echo "<a href='$href'><img src='$src'></a>";
#ricebowl:
using PHP Version 5.2.9/apache 2.0/windows vista - I'm getting Parse error.
anyway, there is working solution:
$dir = "./imageDirectory";
$ext = array('.jpg','.png','.gif');
$dh = opendir($dir);
while (false !== ($filename = readdir($dh))) {
print '<ul>';
if(strpos($filename, '.') > 3)
{
print '<li>'.str_replace($ext, '', $filename).'</li>';
}
print '</ul>';
}
<?php
$directory = "imageDirectory"; // assuming that imageDirectory is in the same folder as the script/page executing the script
$contents = scandir($directory);
if ($contents) {
foreach($contents as $key => $value) {
if ($value == "." || $value == "..") {
unset($key);
}
}
}
echo "<ul>";
foreach($contents as $k => $v) {
echo "<li>link text</li>";
}
echo "</ul>";
?>
This should work, though foreach() can be -computationally- expensive. And I'm sure there must be a better/more-economical way of removing the relative-file-paths of . and .. in the first foreach()

Categories