Sort array by date before pagination after readdir - php

I have code to display images from a folder with pagination. I need to alter it so that it displays the newest image first on page one, and the oldest on the last page. I have tried a few methods but nothing seems to work. Please help!
$mydir = opendir($maindir) ;
$limit = 78;
$offset = ((int)$_GET['offset']) ? $_GET['offset'] : 0;
$files = array();
$page='';
$exclude = array( ".", "..", "index.php",".htaccess","guarantee.gif") ;
while($fn = readdir($mydir))
{
if (!in_array($fn, $exclude))
{
$files[] = $fn;;
}
}
closedir($mydir);
sort($files);
$newICounter = (($offset + $limit) <= sizeof($files)) ? ($offset + $limit) : sizeof($files);
for($i=$offset;$i<$newICounter;$i++) {
//SHOW THE IMAGES HERE
};

You can order the files by its file modification time:
<?php
$mydir = opendir($maindir) ;
$limit = 78;
$offset = ((int)$_GET['offset']) ? $_GET['offset'] : 0;
$files = array();
$page='';
$exclude = array( ".", "..", "index.php",".htaccess","guarantee.gif") ;
while(false !== ($img_file = readdir($mydir))){
if (!in_array($img_file, $exclude)){
# <<<<<<<<<<<<<< CHANGE 1 <<<<<<<<<<<<<<<<
//Put the creation date as the array's key:
$files[date('Y m d, H:i:s',filemtime($img_file))] = $img_file;
}
}
closedir($mydir);
# <<<<<<<<<<<<<< CHANGE 2 <<<<<<<<<<<<<<<<
//order files by date in ascending order:
ksort($files);
//reverse the array (you need the newest files first)
$files = array_reverse($files, false);
/*NOTE: in this point you have your images in $files array which are ordered by the file modification time of each file, so you only need the code to display them. I don't know how are you displaying your images, but that is the easiest part of the problem.*/
foreach($files as $a_image){
echo "<img href='" . $maindir . $a_image ."' alt='Image not found' width='100%' height='auto'/>";
}
?>
It's difficult get the exact creation time of a file in all platforms. So I recommend to you that concatenate the current date with the file name when you create the file.

Related

get full folders tree and count txt files inside

main folder is home - with subfolders and txt files - on various levels
I need the list of entire folders tree - and count txt files inside each of them
This code gives the folders but count is always - 0
I suppose paths to folders and not only folder names - are required, but can't see - how to get them.
function rscan ($dir) {
$all = array_diff(scandir($dir), [".", ".."]);
foreach ($all as $ff) {
if(is_dir($dir . $ff)){
echo $ff . "\n"; // it works
$arr = glob($ff . "/*.txt");
echo count($arr) . "\n"; // always 0
rscan("$dir$ff/");
}
}
}
rscan("home/");
Line 6
$arr = glob($ff . "/*.txt");
Change to the code below:
$arr = glob($dir.$ff . "/*.txt");
An alternate implementation:
<?php
function glob_recursive($pattern, $flags = 0): Int {
$files = glob($pattern, $flags);
$count = count($files);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$count += glob_recursive($dir.'/'.basename($pattern), $flags);
}
return $count;
}
var_dump(glob_recursive('home/*.txt'));
The output is something like:
int(10)

PHP display random n images from directory

I want to display random n number of images from a folder. Currently i am using this script to display images
<?php
$dir = './images/gallery/';
foreach(glob($dir.'*.jpg') as $file) { ?>
<div class="item"><img src="<?php=$file;?>"></div>
<?php } ?>
I want only 10 (or n number) images, that too randomly. How to do this?
The shuffle() method will put the elements of a given array in a random order:
<?php
$dir = './images/gallery/';
function displayImgs($dir, $n=10){
$files = glob($dir.'*.jpg');
shuffle($files);
$files = array_slice($files, 0, $n);
foreach($files as $file) { ?>
<div class="item"><img src="<?php=$file;?>"></div>
<?php }
} ?>
Usage:
displayImgs("/dir/temp/path", 20);
Well, this might be overkill, but you can also use a directory iterator and some randomness to achieve this. I used a modified version of the random numbers generation function from this answer.
make sure that the path you give to the function is relative to the directory in which the script resides, with a slash at the beginning. The __DIR__ constants will not change would you happen to call this script from different places in your file hierarchy.
<?php
function randomImages($path,$n) {
$dir = new DirectoryIterator(__DIR__. $path);
// we need to know how many images we can range on
// but we do not want the two special files . and ..
$count = iterator_count($dir) - 2;
// slightly modified function to create an array containing n random position
// within our range
$positionsArray = UniqueRandomNumbersWithinRange(0,$count-1,$n);
$i = 0;
foreach ($dir as $file) {
// those super files seldom make good images
if ($file->getFilename() === '.' || $file->getFilename() === '..') continue;
if (isset($positionsArray[$i])) echo '<div class="item"><img src="'.$file->getPathname().'"></div>';
$i++;
// change the count after the check of the filename,
// because otherwise you might overflow
}
}
function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
$numbers = range($min, $max);
shuffle($numbers);
return array_flip(array_slice($numbers, 0, $quantity));
}
Let us first create a array and push some random numbers into it. And as per you let $n be 10.
$n = 10;
$arr = array();
for($i = 1; $i <= $n; $i++){
/* Where $n is the limit */
$rand = rand($n);
array_push($arr, $rand);
}
So now we have an array containing the random digits and now we have to echo out the images by iterating over the array:
foreach($arr as $image){
$intToStr = (string) $image;
foreach(glob($dir. $intToStr . '.jpg') as $file){
echo "<div class='item'>$file</div>";
}
}
This would echo out your images.

PHP Create New Folder Dynamically After Thousand Images In Folder

I want to create new folder for images dynamically, when one directory gets 1000 images in there Using PHP, MySQL what is best practice to achieve this kind of thing? :) Thanks
To count the number of files within a folder, I refer you to this answer.
You would then use the mkdir() function to create a new directory.
So you would have something like:
$directory = 'images';
$files = glob($directory . '*.jpg');
if ( $files !== false )
{
$filecount = count( $files );
if ($filecount >= 1000)
{
mkdir('images_2');
}
}
From this example Count how many files in directory php
Add an if statement that will create a folder when files reach a certain number
<?php
$dir = opendir('uploads/'); # This is the directory it will count from
$i = 0; # Integer starts at 0 before counting
# While false is not equal to the filedirectory
while (false !== ($file = readdir($dir))) {
if (!in_array($file, array('.', '..') and !is_dir($file)) $i++;
if($i == 1000) mkdir('another_folder');
}
echo "There were $i files"; # Prints out how many were in the directory
?>
define("IMAGE_ROOT","/images");
function getLastFolderID(){
$directory = array_diff( scandir( IMAGE_ROOT ), array(".", "..") );
//if there is empty root, return zero. Else, return last folder name;
$id = empty($directory) ? 0 : intval( end($directory) );
return $id;
}
$last_dir = getLastFolderID();
$target_path = IMAGE_ROOT . DIRECTORY_SEPARATOR . $last_dir;
$file_count = count( array_diff( scandir( $target_path ), array(".", "..") ) ); // exclude "." and ".."
//large than 1000 or there is no folder
if( $file_count > 1000 || $last_dir == 0){
$new_name = getLastFolderID() + 1;
$new_dir = IMAGE_ROOT . DIRECTORY_SEPARATOR . $new_name;
if( !is_dir($new_dir) )
mkdir( $new_dir );
}
I use these code at my website, FYR
So i solved my problem like this.
i'm using laravel for my php development.
first thing i'm getting last pictures folder and then checking if there is more then 1000 images.
if so i'm creating new folder with current date time.
code looks like this.
// get last image
$last_image = DB::table('funs')->select('file')
->where('file', 'LIKE', 'image%')
->orderBy('created_at', 'desc')->first();
// get last image directory
$last_image_path = explode('/', $last_image->file);
// last directory
$last_directory = $last_image_path[1];
$fi = new FilesystemIterator(public_path('image/'.$last_directory), FilesystemIterator::SKIP_DOTS);
if(iterator_count($fi) > 1000){
mkdir(public_path('image/fun-'.date('Y-m-d')), 0777, true);
$last_directory = 'fun-'.date('Y-m-d');
}
you can try something like this
$dir = "my_img_folder/";
if(is_dir($dir)) {
$images = glob("$dir{*.gif,*.jpg,*.JPG,*.png}", GLOB_BRACE); //you can add .gif or other extension as well
if(count($images) == 1000){
mkdir("/path/to/my/dir", 0777); //make the permission as per your requirement
}
}

how to sort file names having string plus date plus number

I wrote a script to get all the files from a given directory and upload those files to my site. However, I am facing a problem - when I print my filenames of the directory those are coming as follows.
Products010420141400170007.xml
Products010420141402380008.xml
Products010420141406240009.xml
Products100320141739560000.xml
Products180320142116150001.xml
Products180320142121210002.xml
Products210320141150070003.xml
Products240320141643400004.xml
Products310320141848450005.xml
But I need them to sort on the basis of date and the last numbers. Filename format is
"Productsddmmyyhis0001.xml"
Products100320141739560000.xml
Products180320142116150001.xml
Products180320142121210002.xml
Products210320141150070003.xml
Products240320141643400004.xml
Products310320141848450005.xml
Products010420141400170007.xml
Products010420141402380008.xml
Products010420141406240009.xml
How can I achieve this?
Thanks for your answer guys.
I solved it like this. Can you tell me is it fine for future, currently it is working fine.
$files = ftp_nlist($conn_id, ".");
foreach($files as $file)
{
$length = strlen($file);
$key = substr($file,22,($length-22));
$final_array[$key] = $file;
}
ksort($final_array);
While parsing can be done with regex, in your case it's better with substr()
$files = [
'Products010420141400170007.xml',
'Products010420141402380008.xml',
'Products010420141406240009.xml',
'Products100320141739560000.xml',
'Products180320142116150001.xml',
'Products180320142121210002.xml',
'Products210320141150070003.xml',
'Products240320141643400004.xml',
'Products310320141848450005.xml'
];
$f = function($z, $offset)
{
return strtotime(
sprintf(
'%s.%s.%s %s:%s:%s',
substr($z, $offset, 2),
substr($z, $offset+2, 2),
substr($z, $offset+6, 4),
substr($z, $offset+10, 2),
substr($z, $offset+12, 2),
substr($z, $offset+14, 2)
)
);
};
usort($files, function($x, $y) use ($f)
{
$dx = $f($x, 8);
$dy = $f($y, 8);
if($dx==$dy)
{
return substr($x, 22, 4)-substr($y, 22, 4);
}
return $dx-$dy;
});
-since substr() will work much faster. Note, that code above is bound to file name structure and will fail if there will be invalid entries.
It will parse file name with extracting date & time parts with offset and then, if corresponding timestamps are equal, compare numeric (4 digits) postfixes.
I have created the following function to sort files name:
Based on the requirement filename is in this format: Productsddmmyyhis100000000.xml
So the following function will sort filenames based on year, month, date and file number respectively.
// Main funcion to sort filenames
function sort_files($files)
{
$temp_array = array();
foreach ($files as $file)
{
$key = substr($file, 12, 4) . substr($file, 10, 2) . substr($file, 8, 2) . substr($file, 16);
$temp_array[$key] = $file;
}
ksort($temp_array);
return $temp_array;
}
$files = array(
"Products010420141400170007.xml",
"Products010420141402380008.xml",
"Products010420141406240009.xml",
"Products100320141739560000.xml",
"Products180320142116150001.xml",
"Products180320142121210002.xml",
"Products210320141150070003.xml",
"Products240320141643400004.xml",
"Products310320141848450005.xml"
);
$sorted_files = sort_files($files);
echo "<pre>" . print_r($sorted_files, TRUE) . "</pre>";
If the file format is : "Products{ddmmyyyyhhmmss}XXXX.xml"
You should try :
$all = [...]; // array of string with every files names;
$files = array();
foreach($all as $name) {
$year= substr($name,12,4);
$month = substr($name,10,2);
$day = substr($name,8,2);
$hour = substr($name,16,2);
$min = substr($name,18,2);
$sec = substr($name,20,2);
$key = mktime($hour,$min,$sec,$month,$day,$year);
// you got your timestamp
$files[$key] = $name;
}
foreach($files as $name) {
echo $name;
}
It should display your files from the oldest to the most recent.
But you've got a kind of sorted array. If you want classical keys :
// instead of the last foreach :
$all = array();
foreach($files as $name) {
$all[] = $name;
}
// for reversed array : (recent first)
array_reverse($all);

Get latest file trailing number in php

I have something like this in my directory:
slider-1.jpg
slider-2.png
slider-4.gif
slider-8.png
slider-11.gif
Now is there a way to get the last trailing number of "slider" images ?
I need to get this so the next uploaded image should be named slider-12.xxx
I tried for each loop, but it obviously gets me slider-3 as a next name which is false in my case :)
ok, here is how I did it
foreach ($files as $filename) {
$filesarr[]= $filename;
$namearr = explode('.', $filename); //I had to grab this piece as well during the project, so this is main reason not usin Louis proposal.... i needed that array for something else...
$numbers = explode('-', $namearr[1]);
$compare[]=$numbers[2];
}
sort($compare, SORT_NUMERIC);
$assigned_number = end($compare) + 1;
You could try something like this:
$max = 0;
foreach($files AS $file) {
$max = max($max, filter_var($file, FILTER_SANITIZE_NUMBER_INT));
}
$max++;
or this:
natcasesort($files);
$max = filter_var(array_slice($files, -1), FILTER_SANITIZE_NUMBER_INT) + 1;

Categories