How to properly paginate a foreach loop - php

I have a project I am working on, where I scan a directory and pull all of the images from the directory that will display the gallery images. Problem is, some galleries have 300+ images and this is causing a lag. I have looked around, but have not found a proper way of getting my code to paginate. Here is my code snippet of where I am running the foreach loop and getting each image source from the directory:
/** get the model's gallery
===================================================== **/
if(isset($_GET['count'])){
$photo_count = $_GET['count'];
}
if(isset($_GET['model_dir'])){
$model_dir = $_GET['model_dir'];
/** get the higres gallery images
===================================================== **/
$root_directory = $_SERVER['DOCUMENT_ROOT'];
$photo_directory = "{$root_directory}/members/content/model_gallery/{$model_dir}";
$gallery_list = scandir($photo_directory);
$gallery_list = array_diff($gallery_list, array('.', '..'));
foreach($gallery_list as $gallery){
echo "
<a href='{$index_url}join.php'>
<img alt='' src='{$site_url}members/content/model_gallery/{$model_dir}/{$gallery}'
data-image='{$site_url}members/content/model_gallery/{$model_dir}/{$gallery}'
data-description=''>
</a>
";
}
}
Any ideas on how I could go about paginating this code would be greatly appreciated.

I solved the problem myself. For those who had something tangible to respond with, thanks for your help. For others who just wanted to critique code, not knowing what the full purpose of the code is and whether or not it is the final piece of code, should probably keep your input to yourself.
/** get the model's gallery
===================================================== **/
if(isset($_GET['count'])){
$photo_count = mysqli_real_escape_string($_GET['count']);
}
if(isset($_GET['model_dir'])){
$model_dir = mysqli_real_escape_string($_GET['model_dir']);
/** get the higres gallery images
===================================================== **/
$root_directory = $_SERVER['DOCUMENT_ROOT'];
$photo_directory = "{$root_directory}/members/content/model_gallery/{$model_dir}";
$gallery_list = scandir($photo_directory);
$gallery_list = array_diff($gallery_list, array('.', '..'));
$photo_count = $photo_count;
$gallery_limit = 35;
$qty_pages = ceil($photo_count / $gallery_limit);
if (isset($_GET["page"])) { $page = $_GET["page"]; } else { $page=1; }
$start_from = $page * $gallery_limit - $gallery_limit ;
$gallery_list = array_slice($gallery_list,$start_from,$gallery_limit);
echo "<div id='gallery'>";
foreach($gallery_list as $gallery){
echo "
<a href='{$index_url}join.php'>
<img alt='' src='{$site_url}members/content/model_gallery/{$model_dir}/{$gallery}'
data-image='{$site_url}members/content/model_gallery/{$model_dir}/{$gallery}'
data-description=''>
</a>
";
}
echo "</div>";
echo "<div class='contain_pagination'>";
if($photo_count != 0){
echo "<nav class='contain_model_nav'><ul class='pagination'>";
for ($i = 1; $i <= $qty_pages; $i++){
echo "<li><a href='{$index_url}pages.php?id=gallerytour&model_dir={$model_dir}&count={$photo_count}&total={$total_photo_count}&page={$i}'></a>";
echo "</ul></nav>";
}
}
echo "</div>";
}
?>
<script type="text/javascript">
$(document).ready(function(){
$('.pagination').pagination({
items: <?php echo $photo_count;?>,
itemsOnPage: <?php echo $gallery_limit;?>,
cssStyle: 'light-theme',
currentPage: <?php echo $page;?>,
hrefTextPrefix: '<?php echo $index_url ?>pages.php?id=gallerytour&model_dir=<?php echo $model_dir; ?>&count=<?php echo $photo_count; ?>&total=<?php echo $total_photo_count; ?>&page='
});
});
</script>
That is how I was able to paginate the foreach loop. I used nogad's idea for the array_slice function and then I used this open source for the pagination functionality:
http://flaviusmatis.github.io/simplePagination.js/
From there I made sure I had the $photo_count, which contains the count of all images within the directory and essentially what I would be paginating through.
I then set my $gallery_limit per page, which was 35. From there, I determined the number of pages with $qty_pages and dividing by the total $photo_count / and the set $gallery_limit
Next I check if the page isset if it is, then $page is == to the $_GET[page] else it is $page is == 1.
Next I get the $start_from value by multiplying $page * $gallery_limit and then subtracting by $gallery_limit
Next I make the value for the $gallery_list which is an array = to array_slice($gallery_list,$start_from,$gallery_limit);
So my parameters within the function are the entire array of src images for the $gallery_list, the integer of where to start from, and the integer of the $gallery_limit, in this case I set it to a default of 35.
Next I check if $photo_count is != to 0 and then run my normal for loop. the parameters within the url for the anchor will be dependent obviously on your site. One thing to note, is to simply add the &page={$i} parameter to the end of your url.
Finally you use the pagination plugin to write a small jQuery script for the pagination functionality. You should be able to decipher what I did within the jQuery script. I hope this helps someone out, because I have looked at other answers, and none delivered a satisfied result. They were almost as moronic as people like OlegLoginov replying to your question.

Related

(PHP) How do I properly concatenate a list of arrays into a string for file_put_contents?

I've been playing around with a php input function that will build a html page for a game, something like a wiki. All is going fine and dandy but when trying to build an array into a string it's passing back some funny errors.
It's happening to every one that involves an array and I've snipped some code out that works independently to save me time, but just can't figure it out. I'm using the Linux Terminal to run the script and when I set it to echo inside the foreach loop it does it just fine, it just won't when I try building it into a HTML file.
Here is the input script:
echo "\nHow many ranks were there (number)?:\n";
$facInputRankLimit = readline();
echo "Please read carefully and supply the ranks in descending order (HIGHEST > LOWEST):\n";
$facInputRankCount = 0;
$facInputRankString = "";
while ($facInputRankCount < $facInputRankLimit) {
echo "Enter a rank:\n";
$facInputRanks[$facInputRankCount] = readline();
$facInputRankCount++;
}
foreach ($facInputRanks as $facInputRankList) {
$facInputRankString .= $facInputRankList.PHP_EOL;
}
Then I'll build it into a multi-line echo (rather than appending every single block of code):
$facBuildPage = <<<EOT
<?php
\$facRankLimit = '$facInputRankLimit';
\$facRanks = '$facInputRankString';
include('faction2.html');
?>
EOT;
The variables with the backslashes will then be built into "$facFileName.php" and will be a set of variables inputted through this script (input2.php), which will each also include the same html page.
To top it off I'm getting really weird results... if I create 5 ranks, each as "1 2 3 4 5", I actually get "1 2 3" with two vertical linebreaks in between.
Edit: Snipped some of it, I didn't want to risk not adding enough info but it turns out I added a bit much.
For instance, the input I'm giving is:
$facInputRankLimit = 5;
$facInputRanks[1] = 1; -> $facInputRanks[5] = 5;
But it prints:
1<br><br>2<br><br>3
#Deepkak - The relative code in faction2.html is:
<div class="fpDivisions fpBox">
<span class="header">Ranks</span><br>
<?php
$facRankCount = 0;
while ($facRankCount < $facRankLimit) {
echo $facRanks[$facRankCount].'<br>';
$facRankCount++;
}
?>
</div>
I Hope this will solve the issue
<?php
echo "\nHow many ranks were there (number)?:\n";
$facInputRankLimit = readline();
echo "Please read carefully and supply the ranks in descending order (HIGHEST > LOWEST):\n";
$facInputRankCount = 0;
while ($facInputRankCount < $facInputRankLimit) {
echo "Enter a rank:\n";
$facInputRanks[$facInputRankCount] = readline();
$facInputRankCount++;
}
$array = [];
foreach ($facInputRanks as $facInputRankList) {
$array[] = "'".$facInputRankList."'";
}
$facInputRankString = "[".implode(",",$array)."]";
$facBuildPage = <<<EOT
<?php
\$facRankLimit = '$facInputRankLimit';
\$facRanks = $facInputRankString;
include('faction2.html');
?>
EOT;
echo $facBuildPage;
I've created a workaround for this, incase anyone needs any help in the future. It was as simple as echoing it from the HTML page, rather than creating a loop that runs through both the PHP script and the HTML code.
PHP input code:
echo "\nHow many ranks were there (number)?:\n";
$facInputRankLimit = readline();
echo "Please read carefully and supply the ranks in descending order (HIGHEST > LOWEST):\n";
$facInputRankCount = 0;
while ($facInputRankCount < $facInputRankLimit) {
echo "Enter a rank:\n";
$facInputRanks[$facInputRankCount] = readline();
$facInputRankCount++;
}
$facInputList = implode("<br>", $facInputRanks);
PHP output code:
$facBuildPage = <<<EOT
<?php
\$facRanks = '$facInputList';
include('faction2.html');
?>
EOT;
file_put_contents("test/$facFileName.php", $facBuildPage);
HTML output code:
<div class="fpDivisions fpBox">
<span class="header">Ranks</span><br>
<?php echo $facRanks; ?>
</div>

PHP prints variable to screen and code stops running

I am trying to use Parsedown Extra with Parsedown (Have never used either before). I have the code $_GET the selected category (?cat=0) and set it's path & filename to a var. It $_GETs the page number just fine, however when I set the file var, it just prints to the screen and doesn't load my page.
//sets the page (category) number for use with array
//also sets the path to the category's pages
if (isset($_GET['cat'])) {
$catNum = $_GET['cat'];
$catPath = 'content/' . $pageList[$catNum]['path'];
echo '<div class="center pageNav">';
//lists out subpages of catagory
$pageAmt = count($pageList[$catNum]['pages']);
for ($i = 0; $i < $pageAmt; $i++) {
echo '' . $pageList[$catNum]['pages'][$i]['title'] . '';
};
echo '</div>';
//sets path & filename var to selected page: this is the part where it prints the var and doesn't run the rest. The var is pointing to the right file, I checked.
$page = $catPath . $pageList[$catNum]['mainPage'];
} else {
$page = 'content/home.md';
};
//parsedown
require 'parsedown/parsedown.php';
require 'parsedown/parsedownextra.php';
echo ParsedownExtra::instance()
->setBreaksEnabled(true)
->setMarkupEscaped(true)
->text($page);
you have a semi colon at the end of your if statement.
} else {
$page = 'content/home.md';
}; <--
Parsedown takes marked up text and renders it. In your example, you pass $page (which holds a string, a filename) to ->text($page). This parses the string as marked up text, and renders it. So, in your example you are seeing exactly what it is doing. If you are trying to run the text of the file through ->text, you need to load the file contents first and pass to Parsedown.

$_GET not working when trying to view php image in a lightbox style

I have something that im currently working on, however it appears that the $_GET doesn't completely work.
I have a JavaScript light box that brings up an image in a little window, this works however i can only guess that it is using the same URL over and over again.
However when i view the source for the page (and even click one of the links in the source) it will display the correct data.
But the lightbox only seems to display the first image.
This is the JavaScript
<script>
//Checkes if any key pressed. If ESC key pressed it calls the lightbox_close() function.
window.document.onkeydown = function (e)
{
if (!e){
e = event;
}
if (e.keyCode == 27){
lightbox_close();
}
}
</script>
<script>
//This script makes light and fade divs visible by setting their display properties to block.
//Also it scrolls the browser to top of the page to make sure, the popup will be on middle of the screen.
function lightbox_open(){
window.scrollTo(0,0);
document.getElementById('light').style.display='block';
document.getElementById('fade').style.display='block';
}
</script>
<script>
//This makes light and fade divs invisible by setting their display properties to none.
function lightbox_close(){
document.getElementById('light').style.display='none';
document.getElementById('fade').style.display='none';
}
</script>
I wont show the CSS i dont think thats relivant (If someone wants it then ask away)
The relevant part that creates the links is this, its part of a ForEach statement all PHP
$i = 0;
foreach ($nrows as $nrow)
{
$id = $nrow['id'];
$rid = $nrow['RaidID'];
$bid = $nrow['BossID'];
$normal = $nrow['NormalKills'];
$heroic = $nrow['HeroicKills'];
$boss = substr($nrow['BossName'], 0, 3);
$p1 = $id + $bid.".php";
$image = $boss . $p1;
#echo $image;
echo $bid;
if ($oid != $rid)
{
$i = 0;
}
if ($i == 0) {
?><td style="width: 176px;"><center><b><?php echo $nrow['raid']; ?> </b></center></td> </tr><?php
$i++;
}
?><tr><td style="width: 176px;"><div align="left"><?php echo $nrow['BossName']; ?><div id="light"><img src="bossdata/template.php?boss=<?php echo $bid;?>"></a></div><div id="fade" onClick="lightbox_close();"></div>
</div>
<?php
if ($heroic == 0)
{
if ($normal > 0)
{
echo '<img src="images/whiteskull.png" align="right" alt="Normal Kill">';
}
else
{
echo '<img src="images/redx.png" align="right" alt="Not Killed">';
}
}
else
{
echo '<img src="images/redskull.png" align="right" alt="Normal Kill">';
}
?>
</td></tr><?php
$oid = $id;
}
Now this all works, and it actually displays an image with data, however no matter what link i click the boss data is always from the first one on the list.
To me this means that the data is getting through, and reaching the the right parts on image so its "Working", but all the links do the same thing and show the same data :(
*Removed last code Bulk
You have multiple div with the same ID "light" since you create them in a foreach loop.
<div id="light">
Your function lightbox_open() opens all the divs that have id "light".
document.getElementById('light').style.display='block';
That's why you always see the first lightbox. Because the others are behind the first one.
you should try something like this :
function lightbox_open(elem){
window.scrollTo(0,0);
elem.getElementByClass('light').style.display='block';
elem.getElementByClass('fade').style.display='block';
}
And change this :
<a href="#" onclick="lightbox_open();">
By this :
<a href="#" onclick="lightbox_open(this);">
And replace id by class in your div definition :
<div class="light">
$_GET is working correctly in your code.
The issue is in the way you are combining JavaScript and PHP in the second code box. First, all of your divs have the same ID: "light" which is wrong because they all IDs are meant to be unique within the HTML document. You need to identify them uniquely, for example appending the BossID to them.
After identifying each div uniquely you'll have to edit lightbox_open and lightbox_close so they can receive the BossID of the divs that you want to show and hide.

Making Tumblr Widget With "MORE" Button

Alright, so I am trying to create a widget for my website that will display all of my recent blog posts. Tumblr already has a JS that will do this that looks like this.
<script src="blogname.tumblr.com/js"></script>
But I have recently found something better that looks like this.
<img border='0' style='margin:0' id='ji-tumblr-photo-blogname-1' src='' alt='' />
<script src='http://blogname.tumblr.com/api/read/json?number=10&type=photo'></script>
<script>document.getElementById('ji-tumblr-photo-blogname-1').setAttribute('src', tumblr_api_read.posts[0]['photo-url-500']);</script>
Not I'm not too great with JS yet but I kind of figured out that the first line and third line share the same "1", and it kind of acts as a place holder. Now in third line you will see where is says:
tumblr_api_read.posts[0]
Again, I'm not that great with JS but I've found out if you change that number it changes what post it displays from your blog. So for instance, I can take that "1" and increment it from 1-10 and increment the "0" from 0-9 and it will display my last 10 Tumblr posts. From my last post I have found out how to increment numbers with this PHP script.
$offset = 10;
$page = 1;
if (isset($_GET['post']) && is_numeric($_GET['post'])) {
$page = $_GET['post'];
}
$start_number = ($page - 1) * $offset;
$end_number = $start_number + 10;
$num = $start_number;
while ($num <= $end_number) {
echo $num;
$num++;
}
echo sprintf('More', $page + 1);
Now I'm not really that sure "how" it works, but I know that it does work. The only problem is that it displays 0-10, and like I said I need it from 1-10 and 0-9. That way in the "while" loop where it echos out $num I can change it to.
<img border='0' style='margin:0' id='ji-tumblr-photo-blogname-<?php echo $onetoten; ?>' src='' alt='' />
<script src='http://blogname.tumblr.com/api/read/json?number=10&type=photo'></script>
<script>document.getElementById('ji-tumblr-photo-blogname-<?php echo $onetoten; ?>').setAttribute('src', tumblr_api_read.posts[<?php echo $zerotonine; ?>]['photo-url-500']);</script>
And when I press the "more" button it will increment the 0-9 to 10-19. I don't believe I have to change the "$onetoten" because it's just a place holder but for right now I'm stuck... Any help would be amazing!

Remove old parameter in URL (PHP)

I'm using PHP to create a pagination for a table.
I'm using the following code to create the pagination link
<a class='page-numbers' href='$href&pagenum=$i'>$i</a>
With $href
$href = $_SERVER['REQUEST_URI'];
It works well, however, it messes with the address bar, adding each time a new pagenum parameter.
So it becomes pagenum=1&pagenum=3&pagenum=4....
How to improve that?
How about this? Went and tested, to be sure :)
<?php
$new_get = $_GET; // clone the GET array
$new_get['pagenum'] = $i; // change the relevant parameter
$new_get_string = http_build_query($new_get); // create the foo=bar&bar=baz string
?>
<a class="page-numbers" href="?<?php echo $new_get_string; ?>">
<?php echo $i ?>
</a>
Also, note that the whole $href bit is unnecessary. If you start your href with ?, the browser will apply the query string to the current path.
I bet you're going to be looping, though, so here's a version optimized for producing 10,000 page number links. My benchmarks put it as being ever so slightly faster at large numbers of links, since you're just doing string concatenation instead of a full HTTP query build, but it might not be enough to be worth worrying about. The difference is only really significant when there five or six GET parameters, but, when there are, this strategy completes in about half the time on my machine.
<?php
$pageless_get = $_GET; // clone the GET array
unset($pageless_get['pagenum']); // remove the pagenum parameter
$pageless_get_string = http_build_query($pageless_get); // create the foo=bar&bar=baz string
for($i = 0; $i < 10000; $i++):
// append the pagenum param to the query string
$page_param = "pagenum=$i";
if($pageless_get_string) {
$pageful_get_string = "$pageless_get_string&$page_param";
} else {
$pageful_get_string = $page_param;
}
?>
<a class="page-numbers" href="?<?php echo $pageful_get_string; ?>">
<?php echo $i ?>
</a>
<?php endfor ?>
$url = $_SERVER['REQUEST_URI'];
$urlparams = parse_url($url);
if(isset($urlparams['query']){
parse_str($urlparams['query'],$vars);
$vars['pagenum'] = $i;
$urlparams['query'] = http_build_query($vars);
} else {
$urlparams['query'] = 'pagenum='.$i;
}
$url = http_build_url($urlparams);
//http_build_url() is in PECL, you might need to manually rebuild the
//url by looping through it's components:
/*
$url=(isset($urlparams["scheme"])?$urlparams["scheme"]."://":"").
(isset($urlparams["user"])?$urlparams["user"]:"").
(isset($urlparams["pass"])? ":".$urlparams["pass"]:"").
(isset($urlparams["user"])?"#":"").
(isset($urlparams["host"])?$urlparams["host"]:"").
(isset($urlparams["port"])?":".$urlparams["port"]:"").
(isset($urlparams["path"])?$urlparams["path"]:"").
(isset($urlparams["query"])?"?".$urlparams["query"]:"").
(isset($urlparams["fragment"])?"#".$urlparams["fragment"]:"");
*/

Categories