Simple pagination for foreach loop - php

I need a pagination for the output that is generated by a WordPress plugin. The plugin retrieves all products of a certain productgroup from the datebase. The basic code is:
<?php
foreach ((array)$this->view['data']['produkte'] as $p)
{ ?>
...some html code here
}
?>
where $p is an multi-dimensional array that contains the data for the single product.
I'd like to limit the output to, say, 10 products and create a simple pagination for that. The plugin is quite complex and uses nested templates, therefore a custom query is probably not an option in this case.
Would be great if somebody could point me in the right direction. Thank you!
Here's the final code. Thank you very much for your valuable help!!
<?php
$nb_elem_per_page = 3;
$page = isset($_GET['seite'])?intval($_GET['seite']-1):0;
$data = (array)$this->view['data']['produkte'];
$number_of_pages = intval(count($data)/$nb_elem_per_page)+2;
$page_no = $_REQUEST['seite'];
foreach (array_slice($data, $page*$nb_elem_per_page, $nb_elem_per_page) as $p)
{ ?> some HTML here... <?php } ?>
<?php if (count($data) > $nb_elem_per_page) { ?>
<ul id='paginator'>
<?php
for($i=1;$i<$number_of_pages;$i++){
if ($i == $page_no) {?>
<li><?php echo $i ?></li>
<?php }
else { ?>
<li><?php echo $i ?></li>
<?php }} ?>
</ul>
<?php { ?>
Since the default url contains already a query string, I had to modify the code a litte bit. I don't want the current site to have a link in the pagination. This gets me the number of the pagination query string:
$page_no = $_REQUEST['seite'];
I can then easily change the pagination links with a simple if-statement:
if ($i == $page_no) {...}?>
Thanks again!

You may have to tinker this around a bit but that will be something like that :
$nb_elem_per_page = 10;
$page = isset($_GET['page'])?intval($_GET['page']-1):0;
$data = (array)$this->view['data']['produkte'];
$number_of_pages = intval(count($data)/$nb_elem_per_page)+1;
<?php foreach (array_slice($data, $page*$nb_elem_per_page, $nb_elem_per_page) as $p) { ?>
...some html code here
<?php} ?>
<ul id='paginator'>
<?php
for($i=1;$i<$number_of_pages;$i++){?>
<li><a href='./?page=<?=$i?>'>$i</a></li>
<?php}?>
</ul>

You can use array_splice (twice) to get a new array with only the product you need.
Say you want to show 10 items per page and start at page 3:
<?php
$all_products = (array)$this->view['data']['produkte'];
$all_products = array_splice($all_products, 20); //select where to start
$all_products = array_splice($all_products, 0, count($all_products) - 10); //select how many products to show
foreach ($all_products as $p) {
//...some html code here
}
?>
(not tested)
Edit: #Loïc's answer is better as it only uses one array_splice.

Related

How to set condition in following code for marking current page in pagination?

I am trying to set a condition for php- mysql pagination so that it can change the current page "li" to "li class="active" " to mark the current selected page. I am new to php and searching for such pagination tutorial but no luck.
I have done so far what is working but not able to mark selected page. Here $id is for detecting the current page id. How can I set if condition ( or other) so that I can mark the current page item in the pagination? Thousands thanks for helping me.
<ul class="pagination">
<?php if($id > 1) {?> <li>Previous</li><?php }?>
<?php
for($i=1;$i <= $page;$i++){
?>
<?php
if ($id>1)
{ ?>
<li class="active"><?php echo $i;?></li>
<?php }
?>
<!-- <li><?php echo $i;?></li> -->
<?php
}
?>
<?php if($id!=$page)
//3!=4
{?>
<li>Next</li>
<?php }?>
</ul>
You could change your for loop from
<?php
for($i=1;$i <= $page;$i++){
?>
<?php
if ($id>1)
{ ?>
<li class="active"><?php echo $i;?></li>
<?php }
?>
<!-- <li><?php echo $i;?></li> -->
<?php
}
?>
to:
<?php
for($i=1;$i <= $page;$i++){
$class=($i==$id)? ' class="active"' : '';
echo '<li'.$class.'>'.$i.'</li>';
}
?>
If I've understood your code properly, $page represents total pages and $id represents the current page, this will set the current page number as the active class and leave the other pages without the class
Assuming that $id is the current page number, and that $page is the total number of pages, you need to highlight only one by doing the following in your loop:
if($i==$id) // highlight
else // don’t highlight
Your main errors are that you didn’t test whether $i==$id, and you didn’t have an alternative unhighlighted version.
I really think that you should simplify your code by separating your logic from the HTML. It becomes very unreadable otherwise, and very hard to manage.
I have taken the liberty of doing just that. This way you can see where the logic does the hard work, an you only need to print the results in the HTML.
<?php
$id=3; // test value
$page=20; // test value
$li=array(); // temporary array for convenience
$template='<li%s>%s</li>';
if($id>1) $li[]=sprintf($template,'',$id-1,'Previous');
for($i=1;$i<=$page;$i++) {
if($i==$id) $li[]=sprintf($template,' class="active"',$i,$i); // Current
else $li[]=sprintf($template,'',$i,$i);
}
if($id<$page) $li[]=sprintf($template,'',$id+1,'Next');
$li=implode('',$li); // convert to string for printing
?>
<ul class="pagination">
<?php print $li; ?>
</ul>
You will also see two techniques to make things easier:
I use an array as a temporary container. It is easier to add items this way and then to implode it into a string afterwards
sprintf makes it easier to define a template string, so you can manage the HTML component more easily, and fill in the gaps when the time comes.

PHP Foreach , Where

Is there a way of adding a where class to a foreach equation in PHP.
At the moment I am adding an if to the foreach like this.
<?php foreach($themes as $theme){
if($theme['section'] == 'headcontent'){
//Something
}
}?>
<?php foreach($themes as $theme){
if($theme['section'] == 'main content'){
//Something
}
}?>
Presumably the PHP has to loop through all results for each of these. Is there are more efficient way of doing this. Something like
foreach($themes as $theme where $theme['section'] == 'headcontent')
Can this be done
A "foreach-where" would be exactly the same as a "foreach-if", because anyway PHP has to loop through all items to check for the condition.
You can write it on one line to reflect the "where" spirit:
foreach ($themes as $theme) if ($theme['section'] == 'headcontent') {
// Something
}
This becomes really the same as the construct suggested at the end of the question; you can read/understand it the same way.
It does not, however, address the fact that in the question's specific scenario, using any kind of "foreach-where" construction would in effect loop through all items several times. The answer to that lies in regrouping all the tests and corresponding treatments into a single loop.
Use a SWITCH Statement.
<?php
foreach($themes as $theme)
{
switch($theme['section'])
{
case 'headcontent':
//do something
break;
case 'main content':
//do something
break;
}
}
?>
You better use for loop for that like
<?php
$cnt = count($themes);
for($i = 0;$i < $cnt,$themes[$i]['section'] == 'headcontent' ;$i++){
}
?>
If someone uses MVC framework ,the answer to "foreach where" is here
<?php foreach ($plans as $plan) if ($plan['type'] == 'upgrade'): ?>
// Your code here
<?php endif; ?>
Remeber there is no need for the endforeach; statement after endif;
If someone wants to write more code between endif; and endforeach; then the above should be:
<?php foreach ($plans as $plan): if ($plan['type'] == 'upgrade'): ?>
// Your code here
<?php endif; ?>
// More of your code
<?php endforeach; ?>

If - else php query

I need a code that pulls out the listings count for a product in order to have them in the navigation. I am trying to get the product and listing number in the navigation (if there is any), but I don't want to display something if the listings count is equals to 0.
Here follows my code:
<?php if($listingsCount = getListingsCount(0,0,2,2,1,86) > 0): ?>
Bakery
<?php echo $listingsCount['totalRecords'] ?>.
<?php else: ?>
It should be
if ( ($listingsCount = getListingsCount(0,0,2,2,1,86)) > 0)
In this case you the assignment is done first and is then compared to 0. So $listingCount contains the real count.
The way you did it, the comparison is done first and the return value (true/false) is assigned to $listingCount.
Nevertheless. If you never reach the else-part, maybe something in your method getListingsCount() is broken.
Try this:
<?php if (($listingsCount = getListingsCount(0,0,2,2,1,86)) > 0) { ?>
Bakery
<?php echo $listingsCount['totalRecords']; ?>
<?php } else { ?>
Other text
<?php }?>
Thanks guys for your answers. managed to get it working with this...
<?php
$listingsCount = getListingsCount(0,0,2,2,1,86);
if($listingsCount['totalRecords'] > 0):
?>
<dd>
Bakery
[<?php echo $listingsCount['totalRecords'] ?>]
</dd>
<?php endif; ?>

How do I list data from a specific database table as a list with links?

I'm working on my own simple Content Management System to implement on my projects for clients who want to do their own maintenance.
I'm going to contain only page titles and their content in a database table. All I want is to make a list which takes all the page titles and puts them into a <ul>. I believe I should use foreach, but I'm not too good at PHP, so I'd appreciate some help.
So how would I go about this?
<?php
$qry = mysql_query("SELECT * FROM links");
?>
<ul>
<?php while($row = mysql_fetch_array($qry)) { ?>
<li><?php echo $row['link_title']; ?></li>
<?php } ?>
</ul>
...in case your table with links has the colums 'link_url' and 'link_title'. But you get the idea, I guess.
If you have retrieved an array with the table's rows, you can probably do something like this:
The PHP-in-HTML version:
<ul>
<?php foreach( $pages as $page ): ?>
<li><?=$page['title']?></li>
<?php endforeach ?>
</ul>
The HTML-in-PHP version:
echo "<ul>";
foreach( $pages as $page ) {
echo "<li>$page['title']</li>";
}
echo "</ul>";
In both versions $pages is an array containing all the rows from the table.
Maybe you can adapt that to your needs?

Display users as HTML table

I want to display users of wordpress as a table just like
https://stackoverflow.com/users
The recommended function is wp_list_authors, but it is not clear how can customise
the layout.
Say I want to display users in cells of table 5 x 5 with get next page link.
Please advice.
Let me explain a bit.
Unlike get_users_of_blog wp_list_authors does not return an array. If it would - then
having an array I can build any table using foreach. But wp_list_authors builds anchor tags on its own and returns monolith html block. The only option to control layout would be passing some sort before and after tags. But this function does not provide this sort of functionality.
As far as i know, there's no function like get_authors(), but you can do it by a raw SQL query in a custom template:
Update: For pagination
I'm not sure if you can use the built-in WordPress pagination to do that, as the paged param only appear to posts. You could fill a global $post var in a loop or something... There's a lot of approaches, but let's go for the "PHP" one. =D
<?php
$i = 0;
$limit = 25;
$offset = ($o = trim($_GET['offset'])) ? $o : 0;
$users = $wpdb->get_results("SELECT user_nicename ... FROM {$wpdb->users} LIMIT $offset,$limit");
?>
<?php foreach ($users as $user) : ?>
<div class="someclass">
<?php echo $user->user_nicename; ?>
</div>
<?php if ($i++ % $number_of_columns == 0) : ?>
<div class="padder"></div>
<?php endif; ?>
<?php endforeach; ?>
To simulate the table appearance, just float "someclass" left and put a fixed width on it. The "padder" div (float left and width 100%) will ensure that the cells will be aligned by the highest one in that row.
And for the pagination links:
<?php $n = $wpdb->get_var("SELECT count(ID) FROM {$wpdb->users}"); ?>
<?php $o = $offset - $limit; ?>
<?php if ($offset > 0) : ?>
<a class="prev" href="?offset=<?php echo $offset - $limit; ?>">Previous</a>
<?php endif; ?>
<?php $o = $offset + $limit; ?>
<?php if ($o < $n) : ?>
<a class="next" href="?offset=<?php echo $o; ?>">Next</a>
<?php endif; ?>
Code from brain to keyboard. Not tested, again.
Hope it helps.

Categories