Forum Moderators: coopster

Message Too Old, No Replies

preg_match in loop skipping two files

         

RammsteinNicCage

2:35 pm on Jul 19, 2005 (gmt 0)

10+ Year Member



I'm making a gallery script (very difficult for a newb like me) and have run into a little snag. I want to display 16 pics per page and they all have to end with _.jpg. When I put the preg_match in, instead of displaying 16 pics, it only displays 14 pics, skipping the first two. Without the preg_match, it displays the 16 pics (with or without the _.jpg ending). Any idea what I'm doing wrong?

$dir = "example.com/galleries/person/images/";
$dir1 = dir($dir);
$count = count(glob($dir.'*'))/2; // # of files in directory, not including thumbnails
$pics_per_page = 16;
$num_pages = $count / $pics_per_page; // # of full pages
settype($num_pages,"integer"); // make $num_pages a whole number
// determine if an extra page is needed
if ($count % $pics_per_page!=0) {
$num_pages = $num_pages + 1;
}
$page = isset($_GET['page'])? $_GET['page'] : 1; // if page is set, get page, else page = 1
$start_value = ($page * $pics_per_page) - $pics_per_page + 1;

//display pics
print "\n<table>\n";
$j = $start_value;
while ($j < ($start_value + $pics_per_page)) {
if (($file = $dir1->read())!= false) {
if (preg_match("/_.jpg$/", $file)) {
print "<tr><td><img src=\"".$dir.$j."_.jpg\">$j</td></tr>\n";
}
}
$j++;
}
closedir($dir1);

Also, while I'm here, I know I should probably do some security measures because of the $_GET, but if I'm not using any $_GETs (in any general script, not this particular one), there are still plenty of security exploits I have to worry about, right?

Jennifer

coopster

3:20 pm on Jul 19, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Just make sure the files in the directory are truly jpegs and that you have control over what is being placed into that directory.

I'm not sure what exactly is causing your issue yet, but you may want to escape that period in your regular expression as it means more than just punctuation.

if (preg_match("/_\.jpg$/", $file)) {

RammsteinNicCage

3:55 pm on Jul 19, 2005 (gmt 0)

10+ Year Member



Yes, the files are truly jpegs. I did escape the period, but no help.

What do you mean by having control over what's placed into the directory?

Jennifer

coopster

4:01 pm on Jul 19, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Are the files in the directory being uploaded by an end user? Or by you?

RammsteinNicCage

4:03 pm on Jul 19, 2005 (gmt 0)

10+ Year Member



They were uploaded by me.

Jennifer

RammsteinNicCage

4:06 pm on Jul 19, 2005 (gmt 0)

10+ Year Member



I don't know if this helps, but if I change:

$j = $start_value;

to

$j = $start_value - 2;

all 16 images are displayed. I just don't understand why I would have to do that.

Jennifer

coopster

11:39 pm on Jul 19, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



By using glob you are picking up the current directory and previous directory (dot and double dot --> . && .. ) --- make sense?

RammsteinNicCage

2:58 am on Jul 20, 2005 (gmt 0)

10+ Year Member



Well, I was thinking that it could be the . and .. folders, but wouldn't the preg_match that I have exclude them? I did have a more detailed preg_match that specifically excluded them also and still had the same problem. Is the problem that two iterations have to go through in order for it to figure out it has to exclude those files?

Can I change glob to something else so that it doesn't even pick up the folders?

Jennifer

jaski

4:30 am on Jul 20, 2005 (gmt 0)

10+ Year Member



> Can I change glob

$count = count(glob($dir.'*.jpg'))/2; // # of files in directory, not including thumbnails

This should pick only jpg files.

RammsteinNicCage

5:01 am on Jul 20, 2005 (gmt 0)

10+ Year Member



Actually, I just realized that I'm getting the same count whether I use *, *.jpg, or *\.jpg meaning that it's only counting files, so I don't think the problem is in the count variable. :\

However, maybe this line:

if (($file = $dir1->read())!= false) {

is picking up the folders?

Jennifer

coopster

1:19 pm on Jul 20, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member




Well, I was thinking that it could be the . and .. folders, but wouldn't the preg_match that I have exclude them?

Yes, it will, but the $count variable is based on the number of elements returned by the glob() function earlier on, so your count will be 2 more than you expect and also why you are missing two of your jpgs when you loop.

I'm not a big fan of glob [webmasterworld.com]. You may be better off using dir-> to read the files into an array first, getting only those files that you want and count/process that resulting array instead.

RammsteinNicCage

5:41 pm on Jul 21, 2005 (gmt 0)

10+ Year Member



Thanks for the help so far!

I've now changed it to output the directory listing into an array.

$dir = "galleries/person/test/";
$d = dir($dir);
$files= array();
while (false!== ($entry = $d->read())) {
if ( substr($entry, 0, 1)=='.' ) continue;
$files[]= $entry;
}
$d->close();

$count = count($files);
$pics_per_page = 16;

$num_pages = $count / $pics_per_page; // # of full pages
settype($num_pages,"integer"); // make $num_pages a whole number
// determine if an extra page is needed
if ($count % $pics_per_page!=0) {
$num_pages = $num_pages + 1;
}
$page = isset($_GET['page'])? $_GET['page'] : 1; // if page is set, get page, else page = 1
$start_value = ($page * $pics_per_page) - $pics_per_page + 1;

sort($files, SORT_NUMERIC);
$j = $start_value;
print "<ul>";
while ( $j < ($start_value + $pics_per_page)) {
print "<li>" . $files[$j] . " - " . $j . "</li>\n";
$j++;
}
print "</ul>";

My problem is that I don't want the array index to start off at 0, I want it to start off at 1. How can I do that?

Jennifer

coopster

6:12 pm on Jul 21, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Numeric array indexes always start with zero unless otherwise specified. There are a number of tricks. You could always initialize the array.
array[] = 'junk'; 
// loop
array[] = $value;
// end loop
unset(array[0]);

Or another option would be to change the logic in your code later on.

RammsteinNicCage

6:26 pm on Jul 21, 2005 (gmt 0)

10+ Year Member



Works great, thanks for all the help!

Jennifer

coopster

7:11 pm on Jul 21, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



You are very welcome.

RammsteinNicCage

6:30 pm on Jul 29, 2005 (gmt 0)

10+ Year Member



Before I get back to my code review post, I just found another problem and this one is completely baffling me.

I'm having a problem with image_001.jpg being skipped again but my junk image is trying to be displayed, but only on certain galleries. There is no difference in the numbering scheme of the images in different directorys and I have no statements that should only affect certain galleries.

To make this a little easier to understand, this is how the gallery is structured:

Person 1 ($gallery)
- section 1 ($type)
- - page 1 ($page)
- - page 2 ($page)
- section 2 ($type}
- - page 1 ($page)
- - page 2 ($page)

Person 2 ($gallery)
- section 1 ($type)
- - page 1 ($page)
- - page 2 ($page)
- section 2 ($type}
- - page 1 ($page)
- - page 2 ($page)

Videos ($gallery)
- video 1 ($type)
- - page 1 ($page)
- - page 2 ($page)
- video 2 ($type)
- - page 1 ($page)

and so on. All of the types in the Person 1, 2, and 3 galleries might start off with image_001.jpg, but then all of the types in Person 4 might start off with image_002.jpg and end with the junk image. Within the videos gallery, some types work, some don't.
_____________________________________________

$dir = $gallery."/images/".$type."/";
$d = dir($dir);
$abs_dir = "/galleries/".$dir;

//output all files in $dir into an array, then exclude thumbnails and . directory
$files= array();
$files[] = 'junk'; //waste [0] element in array
$index = 1;
while (false!== ($entry = $d->read())) {
if (preg_match("/^_/", $entry) ¦¦ substr($entry, 0, 1)=='.') {
continue;
}
$files[]= $entry;
}
$d->close();
$count = count($files) - 1; //-1 to delete [0] element
$pics_per_page = 16;
sort($files, SORT_REGULAR);
unset($files[0]); //waste [0] element in array

//determine the number of pages needed and what image each page should start with
$num_pages = $count / $pics_per_page; // # of full pages
settype($num_pages,"integer"); // make $num_pages a whole number
// determine if an extra page is needed
if ($count % $pics_per_page!=0) {
$num_pages = $num_pages + 1;
}
$page = isset($_GET['page'])? $_GET['page'] : 1; // if page is set, get page, else page = 1
$start_value = ($page * $pics_per_page) - $pics_per_page + 1;

//begin displaying pics
$j = $start_value;
while ($j < ($start_value + $pics_per_page)) {
if ($j > ($count)) {
break;
} else {
if ($j%4 == 1) {
$template->assign_block_vars('row', array());
}
$template->assign_block_vars('row.cells', array(
'ABS_DIR' => $abs_dir,
'FILE_NAME' => $files[$j])
);
$j++;
}
}

RammsteinNicCage

3:34 pm on Jul 31, 2005 (gmt 0)

10+ Year Member



*bump*

RammsteinNicCage

2:58 pm on Aug 1, 2005 (gmt 0)

10+ Year Member



*final bump*

RammsteinNicCage

8:26 pm on Aug 1, 2005 (gmt 0)

10+ Year Member



Nevermind, I actually figured out the problem. It was because of the sort function - if the files in the $files array were alphabetically before "junk", it sorted junk to the end and the first file would be the one that was skipped.

Jennifer

coopster

1:10 am on Aug 3, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Glad you sorted it, Jennifer. Sorting can be a pain. I remember a few threads where others found sorting to be an issue too...

files sorting in directory [webmasterworld.com]
List files in directory - issue [webmasterworld.com]
Sorting fgetcsv information [webmasterworld.com]