Link to home
Start Free TrialLog in
Avatar of Eternal_Student
Eternal_StudentFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Simple Pagination

Hi guys,

My php is limited so any help/examples are much appreciated.

I have a directory that holds several images for a section as follows:

/literature/
literature1.jpg
literature2.jpg
literature3.jpg
literature4.jpg
literature5.jpg
literature6.jpg
etc ..

What I want is to display "literature1.jpg" with some "descriptive text" on a page.

So the html output would look like:

<p>Here is the text for the following image</p>
<img src="/images/literature/literature1.jpg" />

Now I want these to all work with the same template. So it will load the first by default and then each image/description will be represented by pagination like so:

1, 2, 3, 4, 5, 6, etc

So each number will change the query in the url.

Any ideas on how best to approach this. I have opted against using a database so it is territory I am unfamiliar with.

Thanks.

Avatar of gemdeals395
gemdeals395

Wow, without using a database I guess you could rename the image names like so:

Here_is_the_text_for_the_following_image.jpg

Then when you read the directory you get the names of the files into variables then alter the text based on the way you named it like in the following we replace underscores with spaces and the up arrao shift+6 with a period. Now by formatting how you name each image you can get the results your after with out a database ;)

function formatText($image) {
      $text = explode('.', $image);
      $text = str_replace("_", " ", $text[0]);
      $text = str_replace("^", ".", $text);
      $text = ucfirst($text);
      return $text;
}

$image = 'here_is_the_text_for_the_following_image^.jpg';
$text = formatText($image);

echo("<p>$text</p>");
Also since we are using the command ucfirst() inside the function there is no need to capitolize the first letter of each sentence.

Enjoy ;)
That could easily violate the filename limitations of many filesystems if the text is longer than a short sentence.  XML or an INI file is the best way to go since php has built in support for them (php5 for XML, php4 for INI)
Avatar of Eternal_Student

ASKER

Hi again Click.

I was looking purely for a php method. Like a switch statment or something?

Im just unsure how to work out the pagination part really.
A purely php method for what?  To include the text?  Hard-coding the text into a php file is pretty much the worst way you could do it, but if you're intent on doing that, you can simple store it in an array.  

$items[0] = "some text";
$items[1] = "some more text";

etc...

But I strongly recommend against this.
But surely that is exactly what you would be doing with an INI file?
Well, no.  You could have an ini file for each image which would have the attributes for the image (caption, sizes unless they're all the same size and any other information needed for them).  Or you could even include a base64 encoded version of the image in the ini file.  A database is just an alternate method of storage, the concept behind it is still the same even if you go with the filesystem method, so you still should think in the same terms.
One way you can do it is to have the script in the document root directory, and the ini files (or even php files) in each subdirectory.

If you opt for php, you can use a format like this for the text.  Name it captions.php:
<?php
$caption['literature1.jpg'] = "This is the first caption";
$caption['literature2.jpg'] = "This is the second caption";
$caption['literature3.jpg'] = "This is the third caption";
...
?>

Then, in the doc root, the script should accept a URL like this:
       /show.php?dir=literature&image=literature1.jpg
The image parameter should be optional, too.  The script could work like this:

<?php
$dir = $_GET['dir'];
$image = $_GET['image'];

// validate directory
if (preg_match("#(\.|/)#", $dir)) die('dots and slashes in dir disallowed');
if (!is_dir($dir)) die('bad directory');

include($dir."/captions.php");   // loads in captions

// load all the images into an array
$dh = opendir($dir);
while($d = readdir($dh)) {
  if (!preg_match("#^\.#",$d))  $images[] = $d;
}

// if there's no image specified, use a default
if (!$image) $image=$images[0];

if (preg_match("#/#", $image)) die('slashes in image disallowed');

if (!file_exists($image)) die("image does not exist");

// draw the navigation
for($i=0; $i < count($images); $i++)
{
    $img = $images[$i];
    if ($img != $image)
       echo "<a href=?dir=$dir&image=$img>$i</a>";
    else
       echo "$i";
    if ($i < count($images) - 1) echo ", ";
}
echo "<img src='$dir/$image'>";
echo $captions[$image];

// maybe the images array should be sorted
?>
All of this, including my own suggestions, does add overhead, though.  This is basically the reason why database servers exist.  To offload the overhead of the alternative methods onto a system geared primarily towards it.  Also, when all is said and done, the time and effort of coding it in a way that uses the filesystem instead is on the same level of difficulty as that which would have been used to utilize a database. And likely longer as the code to retrieve information from a database for several database systems is already included in php whereas to do it with any filesystem method, you're going to have to cobble together the pieces dependent on the way you store the information.
I agree that the database method may be easier, but also slower.

jk2001,

Thats a good way of doing it. Is there anyway you can hide the url query in the browser ?

Also, I wanted to pre-load the images using Javascript. Is there anyway of adding that to the process?
Well, no...the database method isn't necessarily slower.  It 'can' be slower, but it depends on a number of factors, not least of which is the makeup of the server it's housed on.  With a dedicated server with fast scsi hard drives and a small number in the data set, yes, it can be faster to use the filesystem.  It's likely you're on a shared hosting server where the filesystem of the server is already heavily used.  This can easily shift the balance of speed.  The only way to actually determine that is to test it.  There's no situation in which it's a 'given'.  Traversing directories can also add overhead that can shift the balance.  Every part of the equation counts.  Accessing a file in a subdirectory can often times be slower than accessing a file in a subdirectory.  For permission reasons if nothing else (and it takes as much time to verify the permissions be it set right or wrong).
Add these two lines to the program, around where the img tag is generated.

$nextimage = $images[$i+1];
if ($nextimage) echo "<img src='$dir/$nextimage' width=1 height=1>";

And adjust your layout so you can hide this image somewhere on the page.

--------------------------
Also, I realized that I didn't need to do the directory traversal.  That was extraneous.

Replace:
// load all the images into an array
$dh = opendir($dir);
while($d = readdir($dh)) {
  if (!preg_match("#^\.#",$d))  $images[] = $d;
}

With:

    $images = array_keys($captions);

I forgot that the filenames are in the caption's keys.
--------------------------

As for the DB versus file...  The DB way is usually easier, but there is some overhead in learning it.  The "file" way depends on naming conventions and whatnot, but, on the other hand, most programmers know the filesystem calls anyway (and if they don't, they eventually will).  Performance-wise, it's important to remember that accessing the db on a shared server results in a file-open, unless you're a very busy site.  The DB runs on top of the file system.

There is an interesting semantic differences between a file hierarchy and sets of tables.  One is a hierarchy, and the other is tabular.  If you want to create a site that has hierarchy and accesses files, you might write less code with the file method.  If you want to simulate "sets" or "tables", then doing it in a DB will map more closely.

I'm not an anti-DB bigot or anything like that.  I appreciate a complex query as much at the next programmer.  Usually, I try to push all the application logic into the database.  I just think when the data is tiny and the queries are simple, it's easier to use files.  This goes double for languages like PHP that have good support for arrays and associative arrays, because they can sometimes "act like" tables.  My usual policy is if I have to do a table join, I'll move it into a DB.
ASKER CERTIFIED SOLUTION
Avatar of John Kawakami
John Kawakami
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Excellent, is that as effective as pre-loading the images using javascript? I take it it loads the next image onto the page so it is downloaded into cache so when they click the next link it will appear pretty rapidly?

Well, it's not quite as good, because it will try to load the next image simultaneously.  A really decent javascript preloader would wait until the first image loaded, then try to start loading the second.  You'd need to use setInterval() to run a function that would do the following:

 check that the main image is loaded
 if it is, then check if the next image is loaded into the second img tag's src
    if it is not, then set the second img tag's src to the next image.
 
Also alter the script so that the image tags have IDs, and the second image tag should load a the main photo, not the next photo.
If I did use javascript to pre-load the images [as I know what they will be called] would this work ok with your script?
Sure.

You can even pass the name of the next image like this:

<script type="text/javascript">
var nextImage = "<?=$dir.'/'.$nextImage?>";
</script>

And the rest of the script is hard-coded afterwards.
Is it possible to pass 2 or 3 images into a javascript variable for pre-load?
Yes.  Use the same technique to pass values to javascript, and write your code to preload them one by one.  You will need to add javascript code to check that an image has loaded, before loading the next image.