Alphabetic vs Random Slideshow?

I am using the following code for a slideshow - which uses whatever images it finds in the specified folder.
The slideshow works but is random and in my experience will not display the last image in the folder (no problem with the image - and all images follow the same naming - incremented by a number at the end of the name - then .jpg)
Can anyone spot the fix I need to make in the code, please? Thanks in advance …
The code is activated from here: nevils-station dot com click on georgia-villager then traillife3252 then the slideshow
This is the actual code (found online & modified a little):
[php]<?
/*
PHP image slideshow - auto version - PHP5
/
// set the absolute path to the directory containing the images
define (‘IMGDIR’, ‘/home3/nevilsst/public_html/georgia-villager/traillife3252/tl-ss-images/’);
// same but for www
define (‘WEBIMGDIR’, ‘http://nevils-station.com/georgia-villager/traillife3252/tl-ss-images/’);
// set session name for slideshow “cookie”
define (‘SS_SESSNAME’, ‘slideshow_sess’);
// global error variable
$err = ‘’;
// start img session
session_name(SS_SESSNAME);
session_start();
// init slideshow class
$ss = new slideshow($err);
if (($err = $ss->init()) != ‘’)
{
header(‘HTTP/1.1 500 Internal Server Error’);
echo $err;
exit();
}
// get image files from directory
$ss->get_images();
// set variables, done.
list($curr, $caption, $first, $prev, $next, $last) = $ss->run();
/

slideshow class, can be used stand-alone
*/
class slideshow
{
private $files_arr = NULL;
private $err = NULL;

public function __construct(&$err)
{
	$this->files_arr = array();
	$this->err = $err;
}
public function init()
{
	// run actions only if img array session var is empty
	// check if image directory exists
	if (!$this->dir_exists())
	{
		return 'Error retrieving images, missing directory';
	}
	return '';
}
public function get_images()
{
	// run actions only if img array session var is empty
	if (isset($_SESSION['imgarr']))
	{
		$this->files_arr = $_SESSION['imgarr'];
	}
	else
	{
		if ($dh = opendir(IMGDIR))
		{
			while (false !== ($file = readdir($dh)))
			{
				if (preg_match('/^.*\.(jpg|jpeg|gif|png)$/i', $file))
				{
					$this->files_arr[] = $file;
				}
			}
			closedir($dh);
		}
		$_SESSION['imgarr'] = $this->files_arr;
	}
}
public function run()
{
	$curr = 1;
	$last = count($this->files_arr);
	if (isset($_GET['img']))
	{
		if (preg_match('/^[0-9]+$/', $_GET['img'])) $curr = (int)  $_GET['img'];
		if ($curr <= 0 || $curr > $last) $curr = 1;
	}
	if ($curr <= 1)
	{
		$prev = $curr;
		$next = $curr + 1;
	}
	else if ($curr >= $last)
	{
		$prev = $last - 1;
		$next = $last;
	}
	else
	{
		$prev = $curr - 1;
		$next = $curr + 1;
	}
	// line below sets the caption name...
	$caption = str_replace('-', ' ', $this->files_arr[$curr - 1]);
	$caption = str_replace('_', ' ', $caption);
	$caption = preg_replace('/\.(jpe?g|gif|png)$/i', '', $caption);
	$caption = ucfirst($caption);
	return array($this->files_arr[$curr - 1], $caption, 1, $prev, $next, $last);
}
private function dir_exists()
{
	return file_exists(IMGDIR);
}

}
?>

/* */ Slideshow body{margin: 0;padding: 0;font: 100% Verdana, Arial, Helvetica, sans-serif;font-size: 14px;} div#gallery{border: 1px #ccc solid;width: 600px;margin: 40px auto;text-align: center;} div#gallery img{margin: 20px;border: 2px #004694 solid;} div#gallery p{color: #004694;} div#gallery div.pn{padding: 10px;margin: 0 5px;border-top: 1px #ccc solid;} a{color:#333;} a:hover{color:#cc0000;} a.sp{padding-right: 40px;}

<?=$caption;?>

First | PreviousNext | Last
[/php]

This bit looks like it could be the culprit.
$curr = 1;
$last = count($this->files_arr);

You’re starting the count at 1 (which is fine.)
$curr = 1;

You’re counting the elements. (which again is fine)
$last = count($this->files_arr);

However, you must be aware that arrays start from 0 (zero)

Take this example:
[php]
$array(‘red’, ‘blue’, ‘green’);

// if i do this:
$last = count($array); // : 3

echo $array[$last]; // output: ‘green’
[/php]

Looks correct doesn’t it?
Well no, actually it’s not.

As i said earlier, computers count from zero so the array above would be indexed 0,1,2
so to print the last one i’d need to do:
[php]
echo $array[2]; // output: ‘green’
[/php]

How do you fix it?
Deduct one from your count like so:
[php]
$last = count($array)-1;
echo $array[$last]; // output: ‘green’
[/php]

Hope that helps,
Red :wink:

I’m a Php newcomer, as is our 19yr old IT major son (who is trying to help but is a step or two behind, in his current course, of my Php adventures), so we’re trying to absorb & use this all at once.

Thank you for your assistance and patience!

I inserted the suggested line of code (see below), subtracting one from the array count, in order to compensate for the default starting-point of zero.

That did solve the failure of the code to display the last file found, thank you for that piece!

The second piece is to get the code to display in the order that it finds the files in the folder, that is, in alpha-numeric order.

The files all begin the same “camping7-9nov2014-” then are numerically incremented e.g. “001.jpg” etc.

The need is for them to display in order rather than randomly.

What aren’t seeing in the code that’s causing a random versus sequential array to be built, please?

[php]class slideshow
{
private $files_arr = NULL;
private $err = NULL;

public function __construct(&$err)
{
	$this->files_arr = array();
	$last = count($array)-1;
	$this->err = $err;
}[/php]

Please disregard previous - it did not resolve the problem.

The array appears to not recognize the first file in the folder.

Looking at the URL …/tl-ss.php?img=0 and …/tl-ss.php?img=1 display the same image and label, that of the second file in the folder.

The array appears to be assigning incorrect sequence values; e.g. the first file recognized is the second file and the middle file is labeled the last.

I can get around among the files but the sequencing is all wrong.

WDYT, please?

BTW: Do I take it correctly that this clears all of the array contents each time the Php is run?

[php]class slideshow
{
private $files_arr = NULL;
private $err = NULL;
[/php]

change this: $curr = 1; to zero. That should order the count properly.

Not quite.

What happens is, you initialise the class using the variable $ss.
Now, each time php is run, you are right to assume the code would be re-run, except this time you have a reference to an existing object of that class called $ss.

You can use classes as many times as you like, even in the same page like so:
$ss1 = new slideshow;
$ss2 = new slideshow;
$ss3 = new slideshow;
and whilst they all use the same class, they are all indeed completely different and independent from each other.

Make sense?
Red :wink:

Lemme try this in code-challenged :-[ terms …

Whatever value is held in variable-Object $ss1 or $ss2, etc. populates Class “new slideshow”

$ss1 & $ss2 are by default empty unless intentionally populated somewhere in the code.

So if I add this line of code at the top of the Php file:

#ss1 = files_arr

… the array will be cleared every time the Php file is run?

I was reading some more about resetting a class and then looked again at the code.

It appears that “isset” is used to check that “files_arr” is empty.

Then it’s unclear to me what the rest of that section of code is doing

I see the test for acceptable image types “if (preg_match(’/^.*.(jpg|jpeg|gif|png)$/i’, $file))”

In this line “$this->files_arr = $_SESSION[‘imgarr’];” is “$_SESSION” clearing “imgarr”?

[php] {
// run actions only if img array session var is empty
if (isset($_SESSION[‘imgarr’]))
{
$this->files_arr = $_SESSION[‘imgarr’];
}
else
{
if ($dh = opendir(IMGDIR))
{
while (false !== ($file = readdir($dh)))
{
if (preg_match(’/^.*.(jpg|jpeg|gif|png)$/i’, $file))
{
$this->files_arr[] = $file;
}
}
closedir($dh);
}
$_SESSION[‘imgarr’] = $this->files_arr;
}
}[/php]

Yes.

$ss1 & $ss2 do not exist until you create them, thereby, initializing the class.
Note: the class is still empty, it’s just ‘ready’

Not quite.

If you wish to reset $ss1 each time the code runs you would simply overwrite it like so:
$ss1 = new Slideshow;
although I don’t know why you would do such a thing.

Let me give you a working example of classes:
[php]
/**

  • this is the basis of a living thing.
    */
    class LivingThing {
    public $legs;
    public $sound;
    public $wings;

    public function __construct() {}

    public function creature() {
    return array(
    ‘legs’ => $this->legs,
    ‘sound’ => $this->sound,
    ‘wings’ => $this->wings
    );
    }
    }
    [/php]

If this code is in my page, when php runs, nothing will happen.

if i use the class then i can do different things with the same code:
[php]
// let’s create a dog.
$creature = new LivingThing;
$creature->legs = 4;
$creature->sound = ‘woof’;
$creature->wings = ‘no’;
$dog = $creature->creature();
print_r($dog);
//Array ( [legs] => 4 [sound] => woof [wings] => no )

// lets’s create a person
$creature = new LivingThing;
$creature->legs = 2;
$creature->sound = ‘talks’;
$creature->wings = ‘no’;
$person = $creature->creature();
print_r($person);
//Array ( [legs] => 2 [sound] => talks [wings] => no )

// let’s create a spider
$creature = new LivingThing;
$creature->legs = 8;
$creature->sound = ‘buzz’;
$creature->wings = ‘no’;
$spider = $creature->creature();
print_r($spider);
//Array ( [legs] => 8 [sound] => buzz [wings] => no )
[/php]

Make sense?
Red :wink:

I was having trouble getting my head around “$this” so found a comparison of “self” and “this” which helped:

-self refers to the current class -self can be used to call static functions and reference static member variables -self can be used inside static functions -self can also turn off polymorphic behavior by bypassing the vtable -$this refers to the current object -$this can be used to call static functions -$this should not be used to call static member variables. Use self instead. -$this can not be used inside static functions

Then, after putting on a fresh pot of coffee, I reread your post and this is what I am understanding:

Class “LivingThing” has variables.

The Class “LivingThing” is, by default, globally recognized.

Variables may be Private or Public - you have made them Public.

The Public Variables are “$legs”, “$sound”, and “$wings”

I do not understand what this does “public function __construct() {}”

This assembles the three Variables associated with the Class “LivingThing” into an Array

[php]public function creature() {

return array(

‘legs’ => $this->legs,

‘sound’ => $this->sound,

‘wings’ => $this->wings[/php]

An Object $creature is created which value comes from a “new LivingThing” Class Array

The values of the three Variables in the Array associated with $creature are “4”, “woof”, and “no”.

The Label attached to this “new LivingThing” is “dog”

The Array associated with “dog” is Printed to the Screen.

[php]$creature = new LivingThing;
$creature->legs = 4;
$creature->sound = ‘woof’;
$creature->wings = ‘no’;
$dog = $creature->creature();
print_r($dog);
//Array ( [legs] => 4 [sound] => woof [wings] => no ) [/php]

Yep, you got it :slight_smile:

This is a magic method (any function/method that starts with a double underscore is a magic method)
It constructs the class when initialized.
As you can see in my example it is empty, i could have done this instead:
[php]
class LivingThing {
public $legs;
public $sound;
public $wings;

public function __construct($legs, $sound, $wings) {
	$this->legs = $legs;
            $this->sound = $sound;
            $this->wings = $wings;
}

public function creature() {
	return array(
		'legs' => $this->legs,
		'sound' => $this->sound,
		'wings' => $this->wings
	);
}

}
[/php]

And then called initialized the class in a slightly different way as these variables are now required.
[php]
// let’s create a dog object.
$creature = new LivingThing(4, ‘woof’, ‘no’); // pass in the values of the variables.
$dog = $creature->creature();
print_r($dog);
//Array ( [legs] => 4 [sound] => woof [wings] => no )
[/php]

$this and self are keywords for accessing methods/variables within a scope.
If you notice in the class i wrote i refer to ‘$this’ what this means is the name of the object.
For example, we have 3 objects: $dog, $person and $spider.

So instead of writing $dog->sound inside the class (meaning im stuck with a variable called dog) I use $this instead. So $cat->sound, $dog->sound, $rabbit->sound would all be different things using the same variables.

self is pretty much the same thing used in static classes - save that tutorial for another day :wink:

Finally, regarding Public|Private.
This means the following:
Public = I can access the variables from anywhere.
Private = I cannot access the variables from outside the class.

Have a read of this, explains far better than i can.
Makes sense?
Red :wink:

I will have to go over this a few times over the next several days for it all to sink in, then will need to practice it some, but I’m getting closer.

Meanwhile, I’m not sure how to fix my slideshow.

This segment of code appears to reset $ss

[php]// start img session
session_name(SS_SESSNAME);
session_start();
// init slideshow class
$ss = new slideshow($err);
if (($err = $ss->init()) != ‘’)[/php]

I just don’t understand why the array that is built later in the code is not alpha-numerically ordered from the first file found to the last. Is there something other than the name of the files that the array may be using to determine order?

One feature I like in the existing code is that, unlike most slideshow code I’ve found, it can access a dynamic folder of image files - rather than requiring a fixed set of specific images.

The next feature I like is to be able to select from among the images found.

The missing feature is a row of several thumbnails (for a quick scan of images found) just below the large selected image centered above the thumbnails.

I’d be happy to discover a different snippet of code with the desired features to replace this.

I could try to write such a code snippet from scratch but that might get real exciting and time-consuming given my obviously minimal Php competence … WDYT?

This bit of code does ‘reset’ the class - only if the session is not set.
[php]$ss->init()[/php]

To create your thumbnails just add in another method for displaying them. You already have the array of images in this variable: $this->files_arr so it’s just a matter of returning that array then using a loop to display them.

Red :wink:

I haven’t disappeared - I fell asleep last night while reading about and testing some different code (I had been up since 6am).

Here’s a summary of the goals:

  1. Handle a dynamic-content folder of .jpg, .gif, .png images

  2. Build an alphanumeric-ordered name-based array

  3. Build a an alphanumeric-ordered name-based thumbnail array

  4. Display and scroll thumbnails horizontally

  5. Display a single large image above scrolling thumbnails (starting by default with the first image in the array & changed based on thumbnail image selected).

Related matters …

Question 1: I read somewhere that for best security the files & folders should be handled via some sort of virtualization vs directly - does that make sense and it is somewhat easy to do?

Question 2: Would this .htaccess security solution prevent the slideshow from working?

(I don’t intentionally provide a way for someone to upload a php file into the images folder … but one never knows.

Thanks!
http://www.itoctopus.com/quick-joomla-security-tip-disable-php-execution-in-the-images-folder

Here’s the new code I’m looking at … between distractions …

[php]

<? require_once "http://nevils-station.com/georgia-villager/traillife3252/tl-php/tl-ss-config.php"; if($_REQUEST[auto] == "on") { $meta = "; "; $nav = "Back | Stop Slideshow | Next"; } if($_REQUEST[auto] == "off" || !$_REQUEST[auto]) { $meta = " "; $nav = "Back | Start Slideshow | Next"; } echo<<<EOF Trail Life - Slideshow/title> $meta EOF; if(!$_REQUEST[image]) { //Default thumbnail page $i = 0; foreach($arr_img as $var_img) { //Grabs all image names in array if($var_img != "") { //Don't show first entry of array - it's blank echo<<<EOF EOF; } $i++; } } else { //Show the slides echo<<<EOF


$nav
EOF; } ?>[/php]

Here’s the associated “tl-ss-config.php”

[php]<?
/* Initial config for tl-ss from dynamic-content image folder to create & display array */
$arr_img = Array();
$handle = opendir(‘http://nevils-station.com/georgia-villager/traillife3252/tl-ss-images/’);
while (false !== ($file = readdir($handle))) {
if ($file != “.” && $file != “…”) {
$arr_img[] = $file;
}
}
$i = 1;
$next = 2;
$back = 0;
while($i <= $total){
if($back == 0) {
$back_link = $total;
} else {
$back_link = $back;
}
if($next == $var_total) {
$next_link = 1;
} else {
$next_link = $next;
}
if ($image == “$i”) {
$next_img = “$next_link”;
$back_img = “$back_link”;
}
$i++;
$next++;
$back++;
}
?>[/php]

Both code snippets test as OK here: http://phpcodechecker.com/

But they don’t work.

When I test here: http://www.draac.com/javatester.html

I get this in a new window:

; "; $nav = "Back | Stop Slideshow | Next"; } if($_REQUEST[auto] == "off" || !$_REQUEST[auto]) { $meta = " "; $nav = "Back | Start Slideshow | Next"; } echo<<

But I get a 404 error if I try “Start Slideshow”.

I’m missing something obvious …

Do you mind me asking why all the HEREDOC strings?
Why not either leave php and use plain html or just use plain old ‘echo’?

I suspect this may be your problem with one of them not closing properly thus printing a portion of code to the screen.

Red :wink:

I’m afraid I had no idea what a “HEREDOC” statement was so I found & read this:

http://php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc

But that site doesn’t explain why a “heredoc” method is bad & should be replaced by HTML5 code.

It does explain that “heredoc” is very fussy - and apparently is not error-checked well (e.g. I ran it through that Php test site & it shows as clean code).

Is the newer “nowdoc” method preferred in Php?

This is a HEREDOC statement:
[php]
echo<<<EOF

 <head>
     <title>Trail Life - Slideshow/title>
     $meta
EOF; [/php]

It would be easier/better to exit php and print in html like so; notice how i go back into php to print the $meta data.
[php]
?>

 <head>
     <title>Trail Life - Slideshow/title>
     <?php echo $meta; ?>
[/php]

hope that helps,
Red :wink:

Thanks!

I tried it in my code (see below) and got an empty screen.

Also, where is “…/$var_img”/" stored?

[php][/php]

Perhaps the contents of “”…/$var_img" /" is not being found?

Or could a Permissions problem be causing “”…/$var_img" /" to not be written?

[php]<?
require_once “http://nevils-station.com/georgia-villager/traillife3252/tl-php/tl-ss-config.php”;
if($_REQUEST[auto] == “on”) {
$meta = “<meta http-equiv=“refresh” content=“2;url=$PHP_SELF?image=$next_img&auto=on” />;
<meta http-equiv=“Content-Type” content=“text/html; charset=iso-8859-1” />”;
$nav = “<a href=”$PHP_SELF?image=$back_img&auto=on">Back |
<a href="$PHP_SELF?image=$image&auto=off">Stop Slideshow |
<a href="$PHP_SELF?image=$next_img&auto=on">Next";
}
if($_REQUEST[auto] == “off” || !$_REQUEST[auto]) {
$meta = " <meta http-equiv=“Content-Type” content=“text/html; charset=iso-8859-1” />";
$nav = “<a href=”$PHP_SELF?image=$back_img&auto=off">Back |
<a href="$PHP_SELF?image=$image&auto=on">Start Slideshow |
<a href="$PHP_SELF?image=$next_img&auto=off">Next";
}

?>

Trail Life - Slideshow/title> <?php echo $meta; ?> EOF; <?Php if(!$_REQUEST[image]) { //Default thumbnail page $i = 0; foreach($arr_img as $var_img) { //Grabs all image names in array if($var_img != "") { //Don't show first entry of array - it's blank echo<<<EOF EOF; } $i++; } } else { //Show the slides echo<<<EOF


$nav
EOF; } ?>[/php]

Yes you made a bit of a mess there :slight_smile:

You shouldn’t comment it out - especially with html comments
Best remove it altogether - one or the other :wink:

and $var_img is set in the loop:
[php] foreach($arr_img as $var_img)[/php]

Red :wink:

Arrggghhh! Need more coffee! :-[

Deleted “” , saved code, ran code … still nada.

Sigh … :-\

Sponsor our Newsletter | Privacy Policy | Terms of Service