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.
Related
I'm working on an IMDB style website and I need to dynamically find the amount of reviews for a movie. The reviews are stored in a folder called /moviefiles/moviename/review[*].txt where the [*] is the number that the review is. Basically I need to return as an integer how many of those files exist in that directory. How do I do this?
Thanks.
Use php DirectoryIterator or FileSystemIterator:
$directory = new DirectoryIterator(__DIR__);
$num = 0;
foreach ($directory as $fileinfo) {
if ($fileinfo->isFile()) {
if($fileinfo->getExtension() == 'txt')
$num++;
}
}
Take a look at the glob() function: http://php.net/manual/de/function.glob.php
You can then use sizeof() to count how many files there are.
First, use glob () to get file list array, then use count () to get array length, the array length is file count.
Simplify code:
$txtFileCount = count( glob('/moviefiles/moviename/review*.txt') );
You can use this php code to get the number of text files in a folder
<div id="header">
<?php
// integer starts at 0 before counting
$i = 0;
$dir = 'folder-path';
if ($handle = opendir($dir)) {
while (($file = readdir($handle)) !== false){
if (!in_array($file, array('.', '..')) && !is_dir($dir.$file))
{
$temp = explode(".",$file);
if($temp[1]=="txt")
$i++;
}
}
}
// prints out how many were in the directory
echo "There were $i files";
?>
</div>
This is a very simple code that works well. :)
$files = glob('yourfolder/*.{txt}', GLOB_BRACE);
foreach($files as $file) {
your work
}
I'm trying to get 2 random results from an array of files in the "related" directory. I've managed to pull two results randomly from the directory but I need to avoid certain results depending on a variable relating to a specific file name.
My code so far is:
$foo = "bar.php";
function random_file($dir) {
$files = opendir($dir . '/*.php');
$rand_files = array_rand($files, 2);
return array(include $files[$rand_files[0]], include $files[$rand_files[1]]);
}
list($file_1,$file_2) = random_file("related");
I'm trying to pull two random results but avoid the file: bar.php. Does anyone know of a way to omit certain results from the array as I can't find anything online even close?
You can use glob function with a specific regex to only select names that are a match for you. This will limit your initial $files variable to results that do satisfy your condition and you can continue and do the random sampling without modifications.
// entries containing foo will not be included
function random_file($dir) {
$files = glob("^(?!bar.php)*");
$rand_files = array_rand($files, 2);
return array(include $files[$rand_files[0]], include $files[$rand_files[1]]);
}
list($file_1,$file_2) = random_file("related");
You also need to consider directories such as '.' and '..'. I think a switch statement and an unset() for those values in your overall array would work. Then once you have an array with files not including what you don't want. You can then pull two randoms and return that array.
This code may not be 100% perfect but should get you in the right direction.
function random_file($dir) {
$fileArray = array();
if (is_dir($dir)) {
if ($dh = opendir($dir . '/*.php')) {
while (($file = readdir($dh)) !== false) {
$fileArray = array_push($fileArray, $file)
}
for( $i = 0; $i < count($fileArray); $i++ ) {
switch($fileArray) {
case '.':
unset($array[$i]);
break;
case '..':
unset($array[$i]);
break;
case 'bar.php':
unset($array[$i]);
break;
}
}
}
closedir($dh);
}
$rand_files_keys = array_rand($fileArray, 2);
$rand_files = $fileArray[$rand_files_keys[0]];
$rand_files = $fileArray[$rand_files_keys[1]];
return $rand_files;
try this. It will keep randomizing your array until it selects two records excluding the bar.php
$rand_files = array_rand($files, 2);
while(in_array("bar.php",$rand_files))
{
$rand_files = array_rand($files, 2);
}
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.
I've managed (well, stackoverflow has shown me how) to search a directory on my server and echo and image. The trouble is the images in the folder are named by an IP camera yy_mm_dd_hh_mm where dd (and other date digits) have either one or two digits. I need them to have a preceeding zero so that I don't end up with, for example, an image taken at 9:50am being treated as a higher value than the photo taken more recently, at 10:05am. (I want it to treat it as 09_50 and 10_05 to fix the issue).
I've looked at search and replace but cannot get this to work within my current code:
function webcam_image () {
foreach (glob( "../camera/IPC_IPCamera*.jpg") as $f ) {
$list[] = $f;
}
sort($list);
echo array_pop($list);
}
example file = IPC_IPCamera_13_7_24_9_57_45.jpg
any help would be much appreciated!
Thanks
Ali
I would ignore the file name altogether and use a DirectoryIterator, fetching the files actual modified date. Something like this might work.
$files = array();
$iterator = new \DirectoryIterator('/path/to/dir');
foreach ($iterator as $file) {
if(! $file->isDot()) $files[$file->getMTime()] = $file->getFilename();
}
ksort($files);
print_r($files);
Take a look here for more information: http://php.net/manual/en/class.directoryiterator.php
If I have understood you correctly, you could handle this by preg_replaceing the files.
So you could loop through your files and do the following
$newFilename = preg_replace('/_([0-9])_/', '_0$1_', $oldFilename);
rename($oldFilename, $newFilename);
You can try something like:
function webcam_image () {
foreach (glob( "../camera/IPC_IPCamera*.jpg") as $f ) {
$digits = explode('_', substr(substr($f, 13), 0, -4));
foreach($digits as &$digit){
$digit = sprintf("%02d", $digit);
}
unset($digit);
$list[] = 'IPC_IPCamera_' . implode('_', $digits) . '.jpg';
}
sort($list);
echo array_pop($list);
}
You can use sprintf()
$list[] = $f;
with the following
$list[] = sprintf("%02s", $f);
I'm using a php script to randomly show images. I've duplicated this script three times because I wanted to show three random images at once - I'm unsure of how to change the php code to show 3 images.
The problem is, I don't want to run into the chance of all three scripts showing the same images at once. Is there something that I could add to this code to make sure that each image displayed is always different?
<?php
$random = "random.txt";
$fp = file($random);
srand((double)microtime()*1000000);
$rl = $fp[array_rand($fp)];
echo $rl;
?>
the html:
<?php include("rotate.php"); ?>
<?php include("rotate.php"); ?>
<?php include("rotate.php"); ?>
*the random.txt just has a list of filenames with links.
Simple solution...
Get the array of random images (you already did this)
Shuffle the array
Pop an image off the end of the array whenever you need one
rotate.php
$random = "random.txt";
$fp = file($random);
shuffle($fb); //randomize the images
in your code
<?php include('rotate.php') ?>
Whenever you need an image
<?php echo array_pop( $fb ) ?>
http://php.net/manual/en/function.array-pop.php
function GetRandomItems($arr, $count)
{
$result = array();
$rcount = 0;
$arrsize = sizeof($arr);
for ($i = 0; ($i < $count) && ($i < $arrsize); $i++) {
$idx = mt_rand($rcount, $arrsize);
$result[$rcount] = trim($arr[$idx]);
$arr[$idx] = $arr[$rcount];
$rcount++;
}
return $result;
}
$listname = "random.txt";
$list = file($listname);
$random = GetRandomItems($list, 3);
echo implode("<BR>", $list);
P.S. Actually, Galen's answer is better. For some reason I forgot about shuffle xD
You can use array_rand() to select more than one random key at a time, like this:
$random = "random.txt";
$fp = file($random);
shuffle($fp);
// You don't need this. The array_rand() function
// is automatically seeded as of 4.2.0
// srand((double)microtime()*1000000);
$keys = array_rand($fp, 3);
for ($i = 0; $i < 3; $i++):
$rl = $fp[$keys[$i]];
echo $rl;
endfor;
This would eliminate the need for including the file multiple times. It can all be done at once.
You could write a recursive function to check if the array ID has already been printed, and if it has, call itself again. Just put that in a for loop to print three times :)
Though keep in mind that truly random images could overlap!
$beenDisplayed = array();
function dispRand($id) {
if (in_array($id, $beenDisplayed)) {
//generate random number
dispRand($id);
}
else {
array_push($beenDisplayed, $id);
}
}
for ($i = 0; $i < 3; $i++) {
dispRand($random_id);
}