vote up 0 vote down star

I have a PHP script that creates a thumbnail and lists an image gallery. The problem I'm having is that it lists it by timestamp on the server but I want it to list 'naturally'.

<?php
# SETTINGS
$max_width = 100;
$max_height = 100;
$per_page = 24;

$page = $_GET['page'];

$has_previous = false;
$has_next = false;

function getPictures() {
	global $page, $per_page, $has_previous, $has_next;
	if ( $handle = opendir(".") ) {
		$lightbox = rand();
		echo '<ul id="pictures">';

		$count = 0;
		$skip = $page * $per_page;

		if ( $skip != 0 )
			$has_previous = true;

		while ( $count < $skip && ($file = readdir($handle)) !== false ) {
			if ( !is_dir($file) && ($type = getPictureType($file)) != '' )
				$count++;
		}
		$count = 0;
		while ( $count < $per_page && ($file = readdir($handle)) !== false ) {
			if ( !is_dir($file) && ($type = getPictureType($file)) != '' ) {
				if ( ! is_dir('thumbs') ) {
					mkdir('thumbs');
				}
				if ( ! file_exists('thumbs/'.$file) ) {
					makeThumb( $file, $type );
				}
				echo '<li><a href="'.$file.'" class="zoom" rel="group">';
				echo '<img src="thumbs/'.$file.'" alt="" />';
				echo '</a></li>';
				$count++;
			}
		}
		echo '</ul>';

		while ( ($file = readdir($handle)) !== false ) {
			if ( !is_dir($file) && ($type = getPictureType($file)) != '' ) {
				$has_next = true;
				break;
			}
		}
	}
}

function getPictureType($file) {
	$split = explode('.', $file); 
	$ext = $split[count($split) - 1];
	if ( preg_match('/jpg|jpeg/i', $ext) ) {
		return 'jpg';
	} else if ( preg_match('/png/i', $ext) ) {
		return 'png';
	} else if ( preg_match('/gif/i', $ext) ) {
		return 'gif';
	} else {
		return '';
	}
}

function makeThumb( $file, $type ) {
	global $max_width, $max_height;
	if ( $type == 'jpg' ) {
		$src = imagecreatefromjpeg($file);
	} else if ( $type == 'png' ) {
		$src = imagecreatefrompng($file);
	} else if ( $type == 'gif' ) {
		$src = imagecreatefromgif($file);
	}
	if ( ($oldW = imagesx($src)) < ($oldH = imagesy($src)) ) {
		$newW = $oldW * ($max_width / $oldH);
		$newH = $max_height;
	} else {
		$newW = $max_width;
		$newH = $oldH * ($max_height / $oldW);
	}
	$new = imagecreatetruecolor($newW, $newH);
	imagecopyresampled($new, $src, 0, 0, 0, 0, $newW, $newH, $oldW, $oldH);
	if ( $type == 'jpg' ) {
		imagejpeg($new, 'thumbs/'.$file);
	} else if ( $type == 'png' ) {
		imagepng($new, 'thumbs/'.$file);
	} else if ( $type == 'gif' ) {
		imagegif($new, 'thumbs/'.$file);
	}
	imagedestroy($new);
	imagedestroy($src);
}

?>

flag
What in the world does it mean to sort something "naturally"? – thedz Jul 27 at 3:43
@thedz: As a human would. php.net/natsort – hobodave Jul 27 at 3:49
@hobodave: ah, interesting. didn't know that. thanks! – thedz Jul 27 at 4:18

3 Answers

vote up 0 vote down check

The trick was to put everything inside an array... I took the liberty of rewriting your getPictures() function... This one implements the sorting.

function getPictures() {
    global $page, $per_page, $has_previous, $has_next;

    if (!is_dir('thumbs')) {
    	mkdir('thumbs');
    }

    if ($handle = opendir(".")) {
    	$lightbox = rand();

    	$files = array();

    	while (($file = readdir($handle)) !== false) {
    		if (!is_dir($file) && ($type = getPictureType($file)) != '') {
    			$files[] = $file;
    		}
    	}

    	natsort($files);

    	$has_previous = $skip != 0;
    	$has_next = (count($files) - $skip - $per_page) > 0;

    	$spliceLength = min($per_page, count($files) - $skip);
    	$files = array_slice($files, $skip, $spliceLength);

    	echo '<ul id="pictures">';

    	foreach($files as $file) {
    		if (!file_exists('thumbs/' . $file)) {
                $type = getPictureType($file);
    			makeThumb($file, $type);
    		}

    		echo '<li><a href="' . $file . '" class="zoom" rel="group">';

    		echo '<img src="thumbs/' . $file . '" alt="" />';

    		echo '</a></li>';
    	}

    	echo '</ul>';
    }
}
link|flag
guess i'm just a complete noob. i plug this in to getpictures but now nothing is showing up. – veepee Jul 29 at 9:03
I just corrected a mistake, try again. – Andrew Moore Jul 29 at 12:03
sweet. thanks for holding my hand through this. appreciate it! – veepee Jul 30 at 6:07
Andrew - the natsort is currently working, however when i go and click on next page, it will show the next page but reloads the same images – veepee Aug 2 at 23:50
nevermind, i added this... $count = 0; $skip = $page * $per_page; if ( $skip != 0) $has_previous = true; thanks! – veepee Aug 3 at 0:08
vote up 2 vote down

You're not even using an array.

Instead of echo'ing your li's as you encounter them you need to put them into an array, indexed by filename.

$output[$file] = '<li>etc</li>';

Then once your loop has completed, you'll need to use a custom function to do a natural key sort, since PHP's natsort() only works on values.

function natksort($array) {
    $keys = array_keys($array);
    natsort($keys);

    $ret = array();
    foreach ($keys as $k) {
        $ret[$k] = $array[$k];
    }

    return $ret;
}

$output = natksort($output);
echo '<ul>';
foreach ($output as $out) {
    echo $out;
}
echo '</ul>';

Edit

Wow, I found this little gem to do the sorting:

uksort($array, 'strnatcasecmp');

Credit: http://www.chipstips.com/?p=269

link|flag
damn i found that too. i'm too slow for SO :( – rezzif Jul 27 at 4:11
vote up 0 vote down

similair to hobodave but i would use php's built in natsort function:


uksort($output, "strnatcmp");
link|flag

Your Answer

Get an OpenID
or
never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.