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..
Related
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....
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!
Having issues trying to perform a foreach within a while loop in PHP. I'm extracting build names from a database table. Those build names happen to be folder names. Within those folders is a folder (either Client or Clients) and within those are folders named after the clients business name. I want the script to show me the build name (accomplished already with an echo) and then list each folder below the build name.
$build_grab = mysql_query("SELECT b_id,b_name FROM builds", $link);
while($build_row = mysql_fetch_array($build_grab))
{
$b_id = $build_row['b_id'];
$b_name = $build_row['b_name'];
$client_dir = is_dir("/somepath/builds/$b_name/Client/");
$clients_dir = is_dir("/somepath/builds/$b_name/Clients/");
if ($client_dir == '1') {
$client_folders = explode(",", exec("ls -1 /somepath/builds/$b_name/Client/"));
} elseif ($clients_dir == '1') {
$client_folders = str_replace("\n","", explode(",", exec("ls -1 /somepath/builds/$b_name/Clients/")));
};
echo $b_name;
echo "\r\n";
foreach($client_folders as $folder)
{
echo $folder;
echo "\r\n";
}
}
Unfortunately this seems to only give me one (1) client folder name per build and it's always the last client (a-z) in the folder.
Example Output:
build-4.0.0.0Client-fbuild-4.0.0.1Client-dbuild-4.0.0.2Client-j
What am I missing here or better yet, is there a more efficient way of doing this? Any help is greatly appreciated!
You're replacing the $client_folders variable each time. You want to create it as an array before you enter the while loop, then do this
if ($client_dir == '1') {
$client_folders[] = explode(",", exec("ls -1 /somepath/builds/$b_name/Client/"));
} elseif ($clients_dir == '1') {
$client_folders[] = str_replace("\n","", explode(",", exec("ls -1 /somepath/builds/$b_name/Clients/")));
};
By the way, this will only enter the first IF, since the second is exactly the same
Rather than using
$client_folders = str_replace("\n","", explode(",", exec("ls -1 /somepath/builds/$b_name/Clients/")));
I would recommend using the following code to list the folders.
if ($folderHandle = opendir(clients_dir)) {
while ($file = readdir($folderHandle) {
echo "$file\n";
}
closedir($folderHandle);
}
You can change that code to be conditional, but it should give you a good list.
exec() only returns the last line of output from the command. You should use the native PHP functions to read the directory list - either opendir/readdir or glob will work.
if ($client_dir == '1') {
$client_folders = glob("/somepath/builds/$b_name/Client/*", GLOB_ONLYDIR);
} elseif ($clients_dir == '1') {
$client_folders = glob("/somepath/builds/$b_name/Clients/*", GLOB_ONLYDIR);
};
Thanks much to mcrumley, your suggestion of using 'glob' fixed it! Sorry crumley, I am apparently to newb to vote up your response. Perhaps other users can help with that.
Thanks also Chris for suggesting mysqli, I will code with it from here out, late adopter here.
Below the new code that resolved the issue.
$build_grab = $mysqli->query("SELECT b_id,b_name FROM builds");
while($build_row = $build_grab->fetch_array())
{
$b_id = $build_row['b_id'];
$b_name = $build_row['b_name'];
$client_dir = is_dir("/somepath/builds/$b_name/Client/");
$clients_dir = is_dir("/somepath/builds/$b_name/Clients/");
if ($client_dir == '1') {
$client_folders = glob("/somepath/builds/$b_name/Client/*", GLOB_ONLYDIR);
} elseif ($clients_dir == '1') {
$client_folders = glob("/somepath/builds/$b_name/Clients/*", GLOB_ONLYDIR);
};
echo $b_name;
echo "\r\n";
foreach($client_folders as $folder)
{
echo $folder;
echo "\r\n";
}
}
Thanks again for everyones help!
I wrote some code to create a text file just once each time I execute the php file.
Its idea is to check all existing files with a specific name then create a text file with the previous name +1
For example, if there is a file called filetext0.txt, my code will create a file called filetext1.txt and so on...
Please help me to find the error in my code:
<?php
for ($i=0; $i=1000; $i=$i+1)
{
$handle = fopen("filetext".$i.".txt","r");
if ($handle) {
fclose($handle);
$s=$i+1
$handlex = fopen("filetext".$s.".txt","w+");
fclose($handlex);
break
}
}
?>
First of all you should use file_exists in the first step.
Then, your problem are missing semi-colon ';' at the end of lines. Check the error messages on your web pages next time ;)
And finally, your code create a file each file it found, not only one.
I'll suggest this code :
$i = 0;
while(true) {
$filename = "filetext".$i.".txt";
if(! file_exists($filename)) {
touch($filename);
break;
}
$i++
}
You do not have to open each and ever file to check if it exists. You should use PHP's directory functions.
// the maximum number
$maxnum = 0;
$d = dir(".");
while (false !== ($entry = $d->read())) {
if (preg_match ('/filetext([0-9]+)\.txt/', $entry, $matches)) {
if ($matches[1] > $maxnum) {
$maxnum = $matches[1];
}
}
}
$d->close();
echo ("The biggest number is: " . $maxnum);
// increment maxnum
$maxnum++;
// creating the file
touch ("filetext" . $maxnum . ".txt");
You need a ; after each statement.
$fileNames = glob('filetext*.txt');
$latestNumber = -1;
foreach($fileNames as $fileName) {
list($fileNumber) = sscanf($fileName,'filetext%d.txt');
$latestNumber = max($latestNumber,$fileNumber);
}
if ($fileNumber > -1) {
$fileName = 'filetext'.($fileNumber+1).'.txt';
touch($fileName);
}
Leaving aside the syntax errors, the algorithm you are using does not scale well. A better solution would be a searching method something like:
function find_next($stub)
{
$increment=1000; // depending on number of files
$offset=0;
for ($x=0; $x<500; $x++) {
$offset+=$increment;
if (file_exists($stub . $offset)) {
if ($increment<0) {
$increment=-1*((integer)($increment/2) ? $increment/2 : 1;
}
} else {
if (file_exists($stub . ($offset-1)) {
return $offset;
}
if ($increment>0) {
$increment=-1*((integer)($increment/2) ? $increment/2 : 1;
}
}
}
return false; // too many files!
}
(NB I'm just typing this stuff - the above may be a bit buggy).
But it'd be a lot better to store a sequence number and increment it each time you add a file.
However do beware that storing transactional data for a multi-user system using files with PHP is a very bad idea.
Yes used file_exists function to find next name for the file.
The above code missed the brace in if condition.
here code for your problem
$i = 0;
while(true) {
$myfile = "myfile".$i.".txt";
if(!file_exists($myfile)) {
$fh = fopen($myfile, 'w');
fclose($fh);
break;
}
$i++;
}
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()