Can this code to loop through photos in a folder be optimised? - php

I have written this code having not used PHP for 2 years now to loop through a folder of photos and write them to the page in alphabetical order. It is a fairly simple request but it took me the best part of 15 minutes to write.
if ($handle = opendir('photos')) {
$count = 0;
$list[] = array();
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$list[$count] = $file;
$count ++;
}
}
closedir($handle);
asort($list);
$sorted_list = array();
$sorted_list = array_values($list);
foreach ($sorted_list as $i => $value) {
echo "<li><img src=\"photos/$sorted_list[$i]\" alt=\"$sorted_list[$i]\" title=\"\"></li>\n";
}
}
Have I written it totally the wrong way? Are there ways I can improve the code? Any constructive feedback gladly received.

You could take advantage of the scandir() function, which will handle reading the directory as well as sorting the results.
$files = scandir('photos');
if ($files !== false)
{
foreach($files as $f) {
if ($f == '..' || $f == '.') continue;
echo '<li><img src="photos/'.$f.'" alt="'.$f.'" title=""></li>'."\n";
}
}
I edited it a bit for readability.

Try this:
$photos = glob('photos/*');
foreach($photos as $photo) {
echo "<li><img src=\"{$photo}" alt=\"{$photo}\" title=\"\"></li>\n";
}
http://us.php.net/manual/en/function.glob.php

You don't need the $count. This will give you the same result
$list[] = array();
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$list[] = $file;
}
}
Replace sorting and displaying with just:
sort($list);
for ($i = 0; $i < count($list); $i++) {
echo "<li><img src=\"photos/{$list[$i]}\" alt=\"{$list[$i]}\" title=\"\"></li>\n";
}

You can replace
foreach ($sorted_list as $i => $value) {
echo "<li><img src=\"photos/$sorted_list[$i]\" alt=\"$sorted_list[$i]\" title=\"\"></li>\n";
}
with
foreach ($sorted_list as $value) {
echo "<li><img src=\"photos/$value\" alt=\"$value\" title=\"\"></li>\n";
}
Then you don't need to call array_values(), because it doesn't matter that the array keys aren't in numeric order.

A simplier way is using the scandir function:
$dir = 'photos';
$files = array_diff( scandir($dir), array(".", "..") );
foreach ($files as $i => $value) {
echo "<li><img src=\"photos/$value\" alt=\"$value\" title=\"\"></li>\n";
}
good luck!

Related

PHP copy images according to time

I want to copy images from one folder to another on server, now I use this code:
<?php
function read_dir($dir)
{
$list = array();
if (is_dir($dir))
{
if ($handle = opendir($dir))
{
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != "..")
{
$list[] = $file;
}
}
}
closedir($handle);
}
return $list;
}
$src="oldfolder";
$dest="newfolder";
$list= read_dir($src);
foreach($list as $key => $val)
{
copy("$src/$val","$dest/$val");
}
echo "Done";
?>
But I need to copy just images selected by time - for example images uploaded between "now" and 5 min. ago..
Can anyone help?
Thanks
Now my PHP is like below. It seems that it run with "Done" result, but nothing is copied..
<?php
function read_dir($dir)
{
$list = array();
if (is_dir($dir))
{
if ($handle = opendir($dir))
{
while (false !== ($file = readdir($handle)))
{
$fpath = 'oldfolder'.$file;
if (file_exists($fpath)) {
if($file != "." && $file != ".." &&
DateTime::createFromFormat('U', filemtime($file)) < new DateTime("-5
minutes"))
{
$list[] = $file;
}
}
}
}
closedir($handle);
}
return $list;
}
$src="oldfolder";
$dest="newfolder";
$list= read_dir($src);
foreach($list as $key => $val)
{
copy("$src/$val","$dest/$val");
}
echo "Done";
?>
So this is my code, that works for me well - copy images between folders according to time (- 5 sec) set by other code in "time.txt" file:
<?php
function read_dir($dir)
{
$list = array();
if (is_dir($dir))
{
if ($handle = opendir($dir))
{
while (false !== ($file = readdir($handle)))
{
$fpath = 'oldfolder/'.$file;
if (file_exists($fpath)) {
$subor = fopen("./time.txt", "r");
$cas_txt=fgets($subor, 11);
fclose($subor);
$cas_zac = DateTime::createFromFormat('U', $cas_txt)->modify('-5 seconds');
if ($file != "." && $file != ".." && DateTime::createFromFormat('U',
filemtime($fpath)) > $cas_zac)
{
$list[] = $file;
}
}
}
}
closedir($handle);
}
return $list;
}
$src="oldfolder";
$dest="newfolder";
$list= read_dir($src);
foreach($list as $key => $val)
{
//copy file to new folder
copy("$src/$val","$dest/$val");
}
echo "Done";
?>
I have two more questions:
Please how can I rotate images in 180° by or after copy? Is it possible in one php code?
How can I send multiple files - images from my code - like an attachments by mail in php?
Thanks for your help.
You should use the filemtime function

Cannot sort the results of this php script descending

Hello I suspect I am being silly but I am new to PHP coding. All I want to do is sort my results from this script below in a descending order, but I don't know what code to add and where to add it. Please can you help me with this.
<?php
$d = dir("01-Newsletters");
while (false != ($entry = $d->read())) {
if ($entry != "." && $entry != "..") {
echo "<tr><td>{$entry}</td><td><a href='01-Newsletters/{$entry}' target=_blank><img src='../../Site_data/Images/more.gif'/></a></td></tr>";}
}
$d->close();
?>
Currently it is giving this result
Previous Newsletters 2014-04-Newsletter.pdf
2014-07-Newsletter.pdf
2014-10-Newsletter.pdf
2015-01-Newsletter.pdf
2015-04-Newsletter.pdf
2015-08-Newsletter.pdf
You can use the following solution:
<?php
$d = dir("01-Newsletters");
$entries = [];
while (false != ($entry = $d->read())) {
if ($entry != "." && $entry != "..") {
$entries[] = $entry;
}
}
$d->close();
//order the entries...
sort($entries, SORT_STRING);
$entries = array_reverse($entries);
//output the $entries in DESC order...
for ($i = 0; $i < count($entries); $i++) {
echo "<tr><td>{$entries[$i]}</td><td><a href='01-Newsletters/{$entries[$i]}' target=_blank><img src='../../Site_data/Images/more.gif'/></a></td></tr>";
}
?>
if the folder name is 2015-8 I assume it is created on that particular day. On the basis of this assumption, you can use the following approach. Get files modified time store it in an array and then sort that array
$dir = "jays";
$d = dir($dir);
while (false != ($entry = $d->read()))
{
if ($entry != "." && $entry != "..")
{
$files[$entry] = filemtime( $dir.'/' . $entry);
}
}
arsort($files);
print_r($files);
$d->close();

display random image url from folder

I have a php code which uses every image in a folder and echos the url on my page.
what i need help with is making the php code randomize the list of urls each time the page is loaded.
The code that i have is:
<?php
if ($handle = opendir('images')) {
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != "..")
{
$thelist .= '<div data-delay="5"><img src="images/'.$file.'"></div>';
}
}
closedir($handle);
}
?>
<?=$thelist?>
many thanks
Easiest solution would be to put all filenames into an array and then use shuffle() to mix it up. Then you can iterate over the array and output the images. It should look something like this:
<?php
$thelist = "";
if ($handle = opendir('images')) {
$images = array();
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
array_push($images, 'images/'.$file);
}
}
closedir($handle);
shuffle($images);
foreach ($images as $image) {
$thelist .= '<div data-delay="5"><img src="'.$image.'"></div>';
}
echo $thelist;
}
?>
By using glob() instead of opendir() you could shorten the code significantly, as glob() returns an array and then you only would need to shuffle that one.
put your file links into an array and shuffle it with the function shuffle()
<?php
if ($handle = opendir('images')) {
$fileTab = array();
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$fileTab[] = $file;
}
}
closedir($handle);
shuffle($fileTab);
foreach($fileTab as $file) {
$thelist .= '<div data-delay="5"><img src="images/'.$file.'"></div>';
}
}
?>
<?=$thelist?>
Instead of directly creating divs in the while loop, use it only to store all urls in an Array. Then shuffel that array, and use a foreach loop in order to populate $thelist.
Why don't you use glob()?
$images = glob('images/*.{jpg,png,gif}', GLOB_BRACE);
shuffle($images);
foreach($images as $image) {
echo '<div data-delay="5">
<img src="', $image ,'">
</div>';
}

Checking for string within a directory of files but not including subdirectories

I'm trying to write a program that will open up a directory (in this case: files/), scan all of the filenames (not including any directories or ".." or ".") within this directory, and search for the filenames in the specified files from the "pages" array. If the filename is NOT found in the pages, the file will be moved to "unused-content".
My current code does not work. How can I achieve this goal?
<?php
if($handle = opendir('files/')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$file_names[] = $entry;
}
}
closedir($handle);
}
$pages = array("page1.html","page2.shtml","page_three.shtml","page4.htm","page5.shtml");
for($x=0; $x<sizeOf($pages); $x++) {
$current_page = file_get_contents($pages[$x]);
for($i=0; $i<sizeOf($file_names); $i++) {
if(!strpos($current_page,$file_names[$i])) {
if (copy("files/".$file_names[$i],"files/unused-content/".$file_names[$i])) {
unlink("files/".$file_names[$i]);
}
}
}
}
?>
Thank you!
You don't need all that long code .. all you need is FilesystemIterator
$pages = array("1.xml","page2.shtml","page_three.shtml","page4.htm","page5.shtml");
$dir = new FilesystemIterator(__DIR__, FilesystemIterator::SKIP_DOTS);
foreach ( $dir as $file ) {
if ($file->isFile() && in_array(strlen($file->getFilename()), $pages)) {
// copy
// unlink
}
}
See another example using GlobIterator
Try to do something like this:
<?php
if($handle = opendir('files/')) {
$i=0;
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$file_names[$i] = $entry;
}
$i++;
}
closedir($handle);
}
$pages = array("page1.html","page2.shtml","page_three.shtml","page4.htm","page5.shtml");
for($x=0; $x<sizeOf($pages); $x++) {
$current_page = file_get_contents($pages[$x]);
for($i=0; $i<sizeOf($file_names); $i++) {
if(!strpos($current_page,$file_names[$i])) {
if (copy("files/".$file_names[$i],"files/unused-content/".$file_names[$i])) {
unlink("files/".$file_names[$i]);
}
}
}
}
?>

scandir() to sort by date modified

I'm trying to make scandir(); function go beyond its written limits, I need more than the alpha sorting it currently supports. I need to sort the scandir(); results to be sorted by modification date.
I've tried a few solutions I found here and some other solutions from different websites, but none worked for me, so I think it's reasonable for me to post here.
What I've tried so far is this:
function scan_dir($dir)
{
$files_array = scandir($dir);
$img_array = array();
$img_dsort = array();
$final_array = array();
foreach($files_array as $file)
{
if(($file != ".") && ($file != "..") && ($file != ".svn") && ($file != ".htaccess"))
{
$img_array[] = $file;
$img_dsort[] = filemtime($dir . '/' . $file);
}
}
$merge_arrays = array_combine($img_dsort, $img_array);
krsort($merge_arrays);
foreach($merge_arrays as $key => $value)
{
$final_array[] = $value;
}
return (is_array($final_array)) ? $final_array : false;
}
But, this doesn't seem to work for me, it returns 3 results only, but it should return 16 results, because there are 16 images in the folder.
function scan_dir($dir) {
$ignored = array('.', '..', '.svn', '.htaccess');
$files = array();
foreach (scandir($dir) as $file) {
if (in_array($file, $ignored)) continue;
$files[$file] = filemtime($dir . '/' . $file);
}
arsort($files);
$files = array_keys($files);
return ($files) ? $files : false;
}
This is a great question and Ryon Sherman’s answer provides a solid answer, but I needed a bit more flexibility for my needs so I created this newer function: better_scandir.
The goal is to allow having scandir sorting order flags work as expected; not just the reverse array sort method in Ryon’s answer. And also explicitly setting SORT_NUMERIC for the array sort since those time values are clearly numbers.
Usage is like this; just switch out SCANDIR_SORT_DESCENDING to SCANDIR_SORT_ASCENDING or even leave it empty for default:
better_scandir(<filepath goes here>, SCANDIR_SORT_DESCENDING);
And here is the function itself:
function better_scandir($dir, $sorting_order = SCANDIR_SORT_ASCENDING) {
/****************************************************************************/
// Roll through the scandir values.
$files = array();
foreach (scandir($dir, $sorting_order) as $file) {
if ($file[0] === '.') {
continue;
}
$files[$file] = filemtime($dir . '/' . $file);
} // foreach
/****************************************************************************/
// Sort the files array.
if ($sorting_order == SCANDIR_SORT_ASCENDING) {
asort($files, SORT_NUMERIC);
}
else {
arsort($files, SORT_NUMERIC);
}
/****************************************************************************/
// Set the final return value.
$ret = array_keys($files);
/****************************************************************************/
// Return the final value.
return ($ret) ? $ret : false;
} // better_scandir
Alternative example..
$dir = "/home/novayear/public_html/backups";
chdir($dir);
array_multisort(array_map('filemtime', ($files = glob("*.{sql,php,7z}", GLOB_BRACE))), SORT_DESC, $files);
foreach($files as $filename)
{
echo "<a>".substr($filename, 0, -4)."</a><br>";
}
Another scandir keep latest 5 files:
public function checkmaxfiles()
{
$dir = APPLICATION_PATH . '\\modules\\yourmodulename\\public\\backup\\';
// '../notes/';
$ignored = array('.', '..', '.svn', '.htaccess');
$files = array();
foreach (scandir($dir) as $file) {
if (in_array($file, $ignored)) continue;
$files[$file] = filemtime($dir . '/' . $file);
}
arsort($files);
$files = array_keys($files);
$length = count($files);
if($length < 4 ){
return;
}
for ($i = $length; $i > 4; $i--) {
echo "Erase : " .$dir.$files[$i];
unlink($dir.$files[$i]);
}
}

Categories