I'm trying to make a gallery using PHP. The images load properly, but the next and previous buttons don't seem to work. Clicking next on picture #1 brings you to picture #3 but clicking back on picture #3 bring you to picture #2 which is correct. How should I change my code to make it so both go in order?
<?php
function listPicturesInDir($dir) {
$dirname = "../pictures/photos/" . $dir . "/";
$images = glob($dirname . "*.jpg");
$previousPic = "null";
foreach ($images as $image) {
$next = next($images);
$name = str_replace(".jpg", "", $image);
$fp = strrpos($name, '/', 5) + 1;
$name = substr($name, $fp, strlen($name));
$id = str_replace(" ", "", $name);
echo '<img class="galleryPics" src="' . $image . '" alt = "' . $name . '" title="'. $name.'"/>';
echo '<div id="' . $id . '" class="modalDialog">';
echo '<div>';
if($previousPic !== "null"){
echo'<img src="../pictures/arrowLeft2.png" alt="Previous photograph" title= "Previous photograph" class="arrow"/> ';
}
if($next !== false){
$name_next = str_replace(".jpg", "", $next);
$fp_next = strrpos($name_next, '/', 5) + 1;
$name_next2 = substr($name_next, $fp_next, strlen($name_next));
$id_next = str_replace(" ", "", $name_next2);
echo'<img src="../pictures/arrowRight2.png" alt="Next photograph" title="Next photograph" class="arrow"/>';
}
echo 'X';
echo '<h2>' . $name . '</h2>';
echo '<img class="modalImg" src="' . $image . '" alt = "' . $name . '"/>';
echo '</div>';
echo '';
echo '</div>';
//echo $next;
$previousPic = $id;
}
}
?>
The problem is that you are using next($images) within a foreach ($images ...) statement, thus modifying the internal array pointer. This may lead to unexpected behavior, as pointed out in the documentation on foreach:
As foreach relies on the internal array pointer, changing it within the loop may lead to unexpected behavior.
This illustrates your problem, using foreach and next:
$images = array('one', 'two', 'three', 'four');
foreach ($images as $image) {
$next = next($images);
echo "$image => $next", PHP_EOL;
}
Output:
one => three
two => four
three =>
four =>
One may think that just replacing the next() with current() would help, but alas:
foreach ($images as $image) {
$next = current($images);
echo "$image => $next", PHP_EOL;
}
Output:
one => two
two => two
three => two
four => two
According to a comment on the foreach documentation page, there used to be a notice on said page stating that:
Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it.
Don't know why that was removed, but if we use a reference for $image then it actually works (note the &):
foreach ($images as &$image) {
$next = current($images);
echo "$image => $next", PHP_EOL;
}
Output:
one => two
two => three
three => four
four =>
But then maybe an old school for loop just makes more sense:
for ($i = 0; $i < count($images); $i++) {
$nextIndex = $i + 1;
$next = ($nextIndex < count($images)) ? $images[$nextIndex] : null;
$image = $images[$i];
echo "$image => $next", PHP_EOL;
}
Output:
one => two
two => three
three => four
four =>
Output from PHP 5.5.20.
$images = sort(glob($dirname . "*.jpg"));
Related
I have very little experience with PHP, but I'm taking a class that has PHP review exercises. One of them is to create a function that uses a loop to return all values of an array except the first value in an unordered list. I'm assuming there's a way to do this using a foreach loop but cannot figure out how. This is what I had but I feel like I am far off:
<?php
$array = array('myName' => 'Becca', 'favColor' => 'violet', 'favMovie' => 'Empire Strikes Back', 'favBook' => 'Lullaby', 'favWeb' => 'twitter.com');
$myName = $array['myName'];
$favColor = $array['favColor'];
$favMovie = $array['favMovie'];
$favBook = $array['favBook'];
$favWeb = $array['favWeb'];
echo '<h1>' . $myName . '</h1>';
function my_function() {
foreach($array == $myName){
echo '<ul>'
. '<li>' . $favColor . '</li>'
. '<li>' . $favMovie . '</li>'
. '<li>' . $favBook . '</li>'
. '<li>' . $favWeb . '</li>'
. '</ul>';
}
}
my_function();
?>
The correct syntax of foreach is
foreach (array_expression as $key => $value)
instead of
foreach($array == $myName){
function that uses a loop to return all values of an array except the
first value
I'm not sure, what exactly you mean by except the first value. If you are trying to remove first element from the array. Then you could have used array_shift
If you are supposed to use loop then
$count = 0;
foreach ($array as $key => $value)
{
if ($count!=0)
{
// your code
}
$count++;
}
Change the code to following
<?php
$array = array('myName' => 'Becca', 'favColor' => 'violet', 'favMovie' => 'Empire Strikes Back', 'favBook' => 'Lullaby', 'favWeb' => 'twitter.com');
$myName = $array['myName'];
echo '<h1>' . $myName . '</h1>';
function my_function($array)
{
$count = 0;
echo "<ul>";
foreach($array as $key => $value)
{
if($key != "myName")
{
echo "<li>".$value."</li>";
}
}
echo "</ul>";
}
my_function($array);
Ive been trying make this display as html list items it just a string that i explode then loop over each item i cant get it to out put correctly. Could some one please show me where im going wrong or suggest an new approch.
this is what ive tried
$path = "1/2/3/4";
$expath = explode("/",$path);
$ret = '';
echo '<ul>';
foreach ($expath as $pitem) {
echo '<li><a href='.$ret .= $pitem. "/".'>'.$pitem.'</a></li>';
}
echo '</ul>';
.
Desired out put on hrefs
1
1/2
1/2/3
1/2/3/4
Desired visual out LIs
1
2
3
4
Output i get be warned
1
12/>212/>23/>312/>23/>34/>4
$path = "1/2/3/4";
$expath = explode("/", $path);
echo '<ul>';
foreach ($expath as $i => $pitem) {
$slice = array_slice($expath, 0, $i + 1);
$path = implode('/', $slice);
echo '<li>' . $pitem . '</li>';
}
echo '</ul>';
$list = explode("/", "1/2/3/4");
This will create an array $list as:
echo $list[0]; // 1
echo $list[1]; // 2
echo $list[2]; // 3
echo $list[3]; // 4
This line is the problem: echo '<li><a href='.$ret .= $pitem. "/".'>'.$pitem.'</a></li>';
Should be formatted like:
echo "<li><a href='{$ret}={$pitem}/'>{$pitem}</a></li>";
or echo '<li>'.$pitem.'</li>';
Its because your $ret. Place that inside the loop. In your code you concatenate $pitem with $ret all older $ret values also get concat.
Try
<?php
$path = "1/2/3/4";
$expath = explode("/",$path);
echo '<ul>';
foreach ($expath as $pitem) {
$ret = '';
echo '<li><a href='.$ret .= $pitem. "/".'>'.$pitem.'</a></li>';
}
echo '</ul>';
If you want = sign tobe there in the url then just change echo by following
echo "<li><a href='$ret=$pitem/'>$pitem</a></li>";
PHP echo with double quotes will print variable value.
I think I'm picking this up pretty well, but I'm just stuck on this. I want to display this menu using an array and foreach loop:
<img src="/img/page-icons/credit-card21.png" />Payments
<a target="_blank" href="/cloud"><img src="/img/page-icons/upload123.png" />Cloud</a>
<a target="_blank" href="/portal"><img src="/img/page-icons/earth208.png" />Portal</a>
So to do that I need to turn that into this line in PHP:
echo '<img src="/img/page-icons/' . $image . '" />' . $title . '';
To fill that out in the loop we need to create something like this... which is where I'm stuck:
foreach( $stamp as $link => $target ){
echo '<a href="/' . $link . '" target="' . $target . '">';
foreach( $stamp[] as $title => $image ){
echo '<img src="/img/page-icons/' . $image . '" />' . $title;
}
echo '</a>';
}
I don't really know how to go about the above, just been messing around with it for a while today. I also don't want to always display target="' . $target . '" on every link.
The array would probably be a two dimensional array? Something like this any way:
$stamp = array(
'link' => array('title' => 'image'),
'link' => array('title' => 'image'),
'link' => array('title' => 'image')
);
EDIT:
There's some confusion of what 'target' is, I want to echo 4 values from an array into a link, target is one of the values. I didn't know how to use that in the array so I just left it out.
When you do:
foreach( $stamp as $link => $target )
The $link variable contains the string "link" and the $target variable is an array such as ['title' => 'image'].
What you should probably do is have an array like this:
// Init links
$links = array();
// Add links
$links[] = array(
'title' => 'My Title',
'href' => 'http://www.google.com',
'target' => '_blank',
'image' => 'image.png',
);
foreach ($links as $link)
{
echo '<a href="'.$link['href'].'" target="'.$link['target'].'">';
echo '<img src="/img/page-icons/' . $link['image'] . '" />';
echo $link['title'];
echo '</a>';
}
This is a bit more flexible approach that lets you add other data items to the structure in the future. That $links array could easily be generated in a loop if you have a different data source such as a database as well.
EDIT
To answer your further question, you can prefix the link building with a set of sane defaults like this:
foreach ($links as $link)
{
// Use the ternary operator to specify a default if empty
$href = empty($link['href']) ? '#' : $link['href'];
$target = empty($link['target']) ? '_self' : $link['target'];
$image = empty($link['image']) ? 'no-icon.png' : $link['image'];
$title = empty($link['title']) ? 'Untitled' : $link['title'];
// Write link
echo "<a href='$href' target='$target'>";
echo "<img src='/img/page-icons/$image' />";
echo $title;
echo "</a>";
}
you can set your array like:
$stamp = array(
'0' => array('title'=>$title 'image'=>$image,'link'=>$link,'target'=>$target),
'1' => array('title'=>$title, 'image'=>$image,'link'=>$link,,'target'=>$target),
'2' => array('title'=>$title 'image'=>$image,'link'=>$link,'target'=>$target)
);
and in foreach you can write
$i=0;
foreach( $stamp as $st=> $target ){
echo '<a href="/' . $st['link'] . '" target="' . $st['target'] . '">';
echo '<img src="/img/page-icons/' . $st['image'] . '" />' . $st['title'];
echo '</a>';
}
I've been trying to accomplish this for a few days. I have a description in each post that has placeholders manually placed where I want the corresponding image to be replaced. For example:
This is the description shortened...
[image]
[image]
Description starts again with a new paragraph continuing...
The placeholders are [image]. With every new post I upload multiple images, but each post may vary from 1-10 images, so a variable amount of [image] placeholders are placed. I have a function that gets all related images to that post and count how many images there are.
Here is the code I have so far, but what's wrong is, for the first two placeholders [image] it shows the first related image twice, then loops and shows the description again, this time with the second image replacing both [image] placeholders.
<?php
foreach ($photos as $picture) {
$count = count($picture);
for($i = 1; $i<= $count; $i++) {
$image = $picture['filename'];
$replace = "[image]";
$image_path = '../../content_management/image_upload/';
$placeholders = array("$replace");
$image_location = array('<a class="fancybox" href="' . $image_path . '' . $image . '" data-fancybox-group="gallery"><img src="' . $image_path . '' . $image . '" /></a>');
$rawstring = $photo_article['description'];
$new_string = $rawstring;
$new_string = str_replace($placeholders, $image_location, $new_string, $i);
echo $new_string;
}
}
?>
And what the output is:
This is the description shortened...
Image1.jpg
Image1.jpg
Description starts again with a new paragraph continuing...
This is the description shortened...
Image2.jpg
Image2.jpg
Description starts again with a new paragraph continuing...
$photos = array(
'photo1' => array(
'filename' => 'image1.png'
),
'photo2' => array(
'filename' => 'image2.png'
),
);
$photo_article['description'] = "This is the description shortened...
[image]
[image]";
foreach ($photos as $picture)
{
$image = $picture['filename'];
$image_path = '../../content_management/image_upload/';
$replacement = '<a class="fancybox" href="' . $image_path . '' . $image . '" data-fancybox-group="gallery"><img src="' . $image_path . '' . $image . '" /></a>';
$photo_article['description'] = preg_replace("~\[image\]~s", $replacement, $photo_article['description'], 1);
}
echo $photo_article['description'];
you're looping but calling the same $picture['filename'] it should be $picture[$i]['filename'] or just foreach ($picture as $thisPic) { $thisPic['filename']; }
I'm new to PHP and I just figured out how to generate content from several arrays to populate 40 divs. It's a product gallery and the different parts are generated via a for loop. Each time through the loop, I'm using the index to not only grab info from the arrays, but also to create a link for the entire div that I want to use as a JQuery Lightbox to show different views of each product. I've already been able to create a link to the first of the images. I've been trying to use the scandir() function, readdir() function to get a list of each image, but I haven't had any success. The images are in folders, _images/products/0/0.jpg (this folder also contains 1.jpg, 2.jpg, etc. Each time through the loop, it changes to _images/products/1/0.jpg - there are more images in this folder too. I need to create a link for each image and add it to the array in a way that will link a distinct Lightbox with each div.
$names = array ('item1', 'item2', 'item3', etc...);
$prices = array ('item1', 'item2', 'item3', etc...);
$number = array ('item1', 'item2', 'item3', etc...);
$serves = array ('item1', 'item2', 'item3', etc...);
$names_size = sizeof($names)
$img_link = "_images/products/"; // used to create the link for $div2
$div1 = "<div id=\"";
$div2 = "\" class=\"products grid_3\"><a href=\"";
$div3 = "\"><h3 class=\"name\">";
$hero_img = "</h3><img class=\"hero\" src=\"_images/heros/";
$li_price = "<ul><li>Price: <span class=\"price\">$";
$li_serves = "<li>Serves: <span class=\"serves\">";
$li_num = "<li>KC# <span class=\"kcnum\">";
$li_close = "</span></li>";
$div4 = "</ul></a></div>";
for ($i = 0; $i < $names_size; $i++) {
$div = $div1 . $names[$i] . $div2 . $img_link . $i . "/0.jpg" . $div3 . ucwords($names[$i]) . $hero_img . $i . ".jpg\" alt=\"" . ucwords($names[$i]) . "\" />";
$div .= $li_price . $prices[$i] . $li_close;
$div .= $li_kc_num . $kc_no[$i] . $li_close;
$div .= $li_serves . $serves[$i] . $li_close;
$div .= $div4;
echo "{$div}" . "\n";
}
The problem I'm having is that before I echo the final $div, I need to add a list of links for the specific product so I can use make the lightbox work for each div. I tried inserting the code (below) just before echoing the completed $div, but I couldn't go any further with it.
$gallery_array = array();
$files = scandir($img_link . $i);
foreach($files as $file) {
array_push($gallery_array, $file);
}
$gallery_array_size = sizeof($gallery_array);
I honestly don't even know if the Lightbox can even work like this. Any ideas?
You don't have to create a $div like that. You can mix php and HTML codes together.
Your $gallery_array is the same as the $files.
<?php
$names = array ('item1', 'item2', 'item3');
$prices = array ('item1', 'item2', 'item3');
$kc_no = array ('item1', 'item2', 'item3');
$serves = array ('item1', 'item2', 'item3');
$names_size = sizeof($names);
$img_link = "_images/products/";
for ($i = 0; $i < $names_size; $i++) {
?>
<div id="<?=$names[$i]?>" class="products grid_3">
<a href="<?=$img_link.$i?>/0.jpg">
<h3 class="name"><?=ucwords($names[$i])?></h3>
<img class="hero" src="_images/heros/<?=$i?>.jpg" alt="<?=ucwords($names[$i])?>" />
<ul>
<li>Price: <span class="price">$<?=$prices[$i]?></span></li>
<li>KC# <span class="kcnum"><?=$kc_no[$i]?></span></li>
<li>Serves: <span class="serves"><?=$serves[$i]?></span></li>
</ul>
<span>Gallery</span>
<ul>
<?php
$files = scandir($img_link . $i);
for ($x = 2; $x < sizeof($files); $x++) {
echo "<li>".$files[$x]."</li>";
}
?>
</ul>
</a>
</div>
<?php
}
?>