How to correctly make pagination with PHP and MongoDB - php

I'm new to Mongodb and php.
I have a problem setting up pagination
This is the code that I'm using:
<?php
require 'vendor/autoload.php';
$mongodb = new MongoDB\Client;
$database = $mongodb->database_test;
$collection = $database->table_test2;
$searchterm = "4x";
$page = isset($_GET['page']) ? (int) $_GET['page'] : 1;
$limit = 20;
$skip = ($page - 1) * $limit;
$next = ($page + 1);
$prev = ($page - 1);
$sort = array('url' => -1);
$cursor = $collection->find(
['page_title' => new MongoDB\BSON\Regex($searchterm, 'i'),],
[
'limit' => $limit,
'skip' => $skip,
'sort' => $sort
]);
echo "<html dir='rtl'>";
foreach ($cursor as $r) {
echo sprintf('<p>Page Title is: %s.<br> page URL is: %s. </p><br>', $r['page_title'], $r['url']);
}
// second part
$total= $cursor->count();
if($page > 1){
echo 'Previous';
if($page * $limit < $total) {
echo ' Next';
}
} else {
if($page * $limit < $total) {
echo ' Next';
}
}
$mongodb->close();
?>
The first part of the code apparently works fine, I get the results corectly.
the second part of the code
$total= $cursor->count();
if($page > 1){
echo 'Previous';
if($page * $limit < $total) {
echo ' Next';
}
} else {
if($page * $limit < $total) {
echo ' Next';
}
}
$mongodb->close();
has a issue were I don't get the next/previous links but if I manually change the URL and add page=2 I can see results but no navigation links.
if I comment-out:
$total= $cursor->count();
I'm able to get the "Previous" navigation link but not the "next" navigation link.
I'll appreciate any help and advise to correct this code so both the "next" and the "previous" navigation links will appear.
and also if possible, how to show the number of the results found.

Related

Pagination does not work perfectly

I have the following code:
$max = 4;
$page = isset($_GET['page']) ? ($_GET['page']) : '1';
$init = $page - 1;
$init= $max * $init;
$strCount = "SELECT COUNT(*) AS 'total_mytable' FROM mytable";
$varstrCount = $crud->viewdatas($strCount);
$total = 0;
if(count($varstrCount)){
foreach ($varstrCount as $row) {
$total = $row["total_mytable"];
}
}
$result = "SELECT * FROM mytable ORDER BY id_mytable LIMIT $init,$max";
$varresult = $crud->viewdatas($result);
content of page:
<?php
if(count($varresult)){
foreach ($varresult as $res) {
?>
<h5><?php echo $res['title'] ?></h5>
<?php
}
}
?>
<?php
$max_links = 10;
$previous = $page - 1;
$next = $page + 1;
$pgs = ceil($total / $max);
if($pgs > 1 ){
if($previous > 0){
echo "<li><a href='".BASE_URL."/category/$previous' aria-label='Previous'><span aria-hidden='true'>«</span></a></li>";
} else{
}
for($i=$page-$max_links; $i <= $pgs-1; $i++) {
if ($i <= 0){
}else{
if($i != $page{
if($i == $pgs){ //if end insert 3 dots
echo "<li><a href='".BASE_URL."/category/".($i)."'>".$i."</a></li> ...";
}else{
echo "<li><a href='".BASE_URL."/category/".($i)."'>".$i."</a></li>";
}
} else{
if($i == $pgs){ //if end insert 3 dots
echo "<li>".$i."</li> ...";
}else{
echo "<li>".$i."</li>";
}
}
}
}
if($next <= $pgs){
echo "<li><a href='".BASE_URL."/category/$next' aria-label='Next'><span aria-hidden='true'>»</span></a></li>";
}else{
}
}
?>
The result:
And I not understand the reason for the active number stay right off the paging menu
In the code I defined max-links for 10, but no show number 5 and if I define max links for 3 changes nothing , displays the same result as the image.
Thanks for any help
echo "<li>".$i."</li>";
on the above line add up a href, seems like you have css formatting for li>a because of which you are not getting the required formatting on only li. so for getting better formatting for all paging links current, prev, next. you need to add up a tags.
echo "<li><a>".$i."</a></li>"; //in your else part

Pagination in MongoDB database for PHP language

I have the following code for the pagination(PHP) in MongoDB database.
<?php
$mongodb = new Mongo("vvv");
$database = fff
$collection = gggg
$page = isset($_GET['page']) ? (int) $_GET['page'] : 1;
$limit = 12;
$skip = ($page - 1) * $limit;
$next = ($page + 1);
$prev = ($page - 1);
$sort = array('createdAt' => -1);
$cursor = $collection->find()->skip($skip)->limit($limit)->sort($sort);
foreach ($cursor as $r) {
--------
}
$total= $cursor->count();
if($page > 1){
echo 'Previous';
if($page * $limit < $total) {
echo ' Next';
}
} else {
if($page * $limit < $total) {
echo ' Next';
}
}
$mongodb->close();
?>
BUT my database size is 30GB+, each search provides the results of 20,000 which takes HUGE TIME to count() //$total= $cursor->count();
Can any one provide any PHP pagination code for MongoDB which does not count the total number of results but do the pagination?
cursor.skip() requires the server to walk from the beginning of the collection or index to get the offset or skip position before beginning to return results. It is not recommended to use it in pagination against 30GB+ data in your case.
If you cannot narrow a little bit your condition in find(), you can consider to add a sequence number in your docs for pagination purpose, assuming that you will rarely remove/update those documents:
{
createdAt: "2015-01-01",
...
seq_no: 1
},
{
createdAt: "2015-01-02",
...
seq_no: 2
}
Then you can implement the pagination query like this (remember to create the index on seq_no, of course):
$cursor = $collection->find({"seq_no": {"$gt":$skip, "$lte":($skip+$limit)}})

PHP Pagination with x amount of pages

Currently I have a functioning pagination script, although I'm missing on feature. At the moment it's possible for hundreds of pages to be showing in the $pages list, because there's no filter on to show between, for example, [1] [...] 5, 6, 7 [..] [45]. Here's my code:
/** Pagination **/
$limit = 7;
$query = "SELECT COUNT(*) FROM users";
$result = $db->prepare($query);
$result->execute();
$pages_query = $result->fetchColumn(0);
$count = number_format($pages_query);
$pages = ceil($pages_query / $limit);
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
$start = ($page - 1) * $limit;
ob_start();
echo("<span class='alignright'>");
if ($pages >= 1 && $page <= $pages){
if($page > 1){
$next = ($page - 1);
$link = "?page=$next";
echo("<a class='paginate' href='$link'><i class='icon-caret-left'></i></a>");
}
for ($x=1; $x<=$pages; $x++){
echo ($x == $page) ? "<strong style='font-weight: bold!important;'><a class='paginate' href='?page=$x'>$x</a></strong>" : "<a class='paginate' href='?page=$x'>$x</a>";
}
if($page < $pages){
$next = ($page + 1);
$link = "?page=$next";
echo("<a class='paginate' href='$link'><i class='icon-caret-right'></i></a>");
}
echo("</span>");
if($count > 0){
echo("<span class='smalltext'>Page <strong class='half'>$page</strong> of $pages:</span>");
} else {
echo("<span class='smalltext'>There are <span class='half'>$count</span> results to display.</span>");
}
$pagintion = ob_get_clean();
(It's been stripped from other junk that was in it but that's the general frame.) Basically I'm trying to figure out how to limit it to have "between pages" down the bottom as specified in the top part of the question. Something like:
[<] [1] ... [4] [5] [6] ... [45] [>]
If that makes sense.
you can try LIMIT with in your query itself
SELECT * FROM TABLE_NAME LIMIT STARTING_RESULT_NUMBER, RESULTS_PER_PAGE
RESULTS_PER_PAGE is no.of items per page you want to display
STARTING_RESULT_NUMBER =(CURRENT_PAGE_NUMBER*RESULTS_PER_PAGE)
In order to change the list of pages to something like [<] [1] ... [4] [5] [6] ... [45] [>] rather than showing all pages numbers, you can replace your for loop by something like :
echo "<a class='paginate' href='?page=1'>1</a>";
if($page > 3) {echo "...";}
if($page > 2) {echo "<a class='paginate' href='?page=" . $x-1 . "'>" . $x-1 "</a>";}
if($page != 1 && $page != pages) {echo "<a class='paginate' href='?page=" . $x . "'>" . $x "</a>";}
if($page < $pages-1) {echo "<a class='paginate' href='?page=" . $x+1 . "'>" . $x+1 "</a>";}
if($page < $pages-2) {echo "...";}
if($pages >1) {echo "<a class='paginate' href='?page=1'>1</a>";}
Il will show the first page, the last pages, the current pages and the ones just before and just after.
My personal meaning with pagination is that it must be readable and simple to change later on.
I typed the following code based on you're example:
$totalPages = 145; //the total amount of pages
$selectedPage = 40; //the selected page
$pages = array(); //the array which is gonna hold the pages we need to display
$offset = 3; //the number of pages to select around the selected page
$closePages = range($selectedPage - $offset, $selectedPage + $offset); //select the pages that are in $offset of the selected page
array_filter($closePages, function($x) { //filter the pages below 1 and above $totalPages
return ($x <= $totalPages && $x >= 1 ? true : false );
});
array_push($pages, 1); //add the first page
array_push($pages, '...'); //add some dots
$pages = array_merge($pages, $closePages);
array_push($pages, '...'); //and again add some dots
array_push($pages, $totalPages); //add the last page
Then you use a foreach loop to display the pages:
foreach($pages as $page) {
if (is_numeric($page)) {
if ($page != $selectedPage) $content .= ' ' . $page . ' ';
else $content .= ' <strong>' . $page . '</strong> ';
} else
$content .= '[...]';
}
Some explanation after you're comment on this answer:
The $totalPages variable must be the total amount of pages on the page (from you're example) and the $selectedPage is the page that is selected at this moment.
$totalPages = ceil($pages_query / $limit);
$selectedPage = isset($_GET['page']) ? $_GET['page'] : 1;

Adding previous(back) and next buttons next to the page numbers PHP

I have two tiny little problems;
1 . I want to add a previous / next button into this code
2 . I want it to only show like max 10 links between previous and next. So if i have 50 numbers/links it will only show 10 of them and not 50 links on the page.
I have searched on the clo
The code works, only need that two options in it.
Can someone help me out? Thank you !
<?php
include 'includes/connection.php';
$per_page = 8;
$pages_query = mysql_query("SELECT COUNT(`id`) FROM `products`");
$pages = ceil(mysql_result($pages_query, 0) / $per_page);
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
$start = ($page - 1) * $per_page;
$query = mysql_query("SELECT `name` FROM `products` LIMIT $start, $per_page");
while ($query_row = mysql_fetch_assoc($query)) {
echo '<p>', $query_row['name'] ,'</p>';
}
if ($pages >= 1 && $page <= $pages) {
for ($x=1; $x<=$pages; $x++) {
//echo $x, ' ';
echo ($x == $page) ? '<strong>'.$x.'</strong> ' : ''.$x.' ';
}
}else{
header("location:index.php?page=1");
}
?>
First of all, you should, just for good practice, put an "exit;" after the header() call at the end. It doesn't make a difference in this particular script, but keep in mind that any code following a header("Location: ...") call WILL be executed before redirection.
Now to your question, try this (UPDATE: This code has been tested and works.)
<?php
include 'includes/connection.php';
$per_page = 8;
$pages_query = mysql_query("SELECT COUNT(`id`) FROM `products`");
$pages = ceil(mysql_result($pages_query, 0) / $per_page);
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
$start = ($page - 1) * $per_page;
$query = mysql_query("SELECT `name` FROM `products` LIMIT $start, $per_page");
while ($query_row = mysql_fetch_assoc($query))
{
echo '<p>' . $query_row['name'] . '</p>';
}
// If the requested page is less than 1 or more than the total number of pages
// redirect to the first page
if($pages < 1 || $page > $pages)
{
header('Location: ?page=1');
// end execution of the rest of this script
// it will restart execution after redirection
exit;
}
// If more than one page, show pagination links
if($pages > 1)
{
$html = array();
$html[] = '<strong>';
// if you're on a page greater than 1, show a previous link
$html[] = (($page > 1) ? 'Previous ' : '');
// First page link
$pageFirst = '1';
$html[] = (($page == 1) ? "</strong>{$pageFirst}<strong>" : $pageFirst);
if ($pages > 6)
{
$start_cnt = min(max(1, $page - (6 - 1)), $pages - 6);
$end_cnt = max(min($pages, $page + 4), 8);
$html[] = ($start_cnt > 1) ? '...' : ' ';
for ($i = $start_cnt + 1; $i < $end_cnt; $i++)
{
$html[] = ($i == $page) ? '</strong>' . $i . '<strong>' : '' . $i . '';
if ($i < $end_cnt - 1)
{
$html[] = ' ';
}
}
$html []= ($end_cnt < $pages) ? '...' : ' ';
}
else
{
$html[] = ' ';
for ($i = 2; $i < $pages; $i++)
{
$html[] = ($i == $page) ? '</strong>' . $i . '<strong>' : '' . $i . '';
if ($i < $pages)
{
$html[] = ' ';
}
}
}
// last page link
$pageLast = '' . $pages . '';
$html[] = (($page == $pages) ? "</strong>{$pageLast}<strong>" : $pageLast);
// Show next page link if you're on a page less than the total number of pages
$html[] = ($page < $pages) ? ' Next' : '';
// If you're not on the last page, show a next link
$html[] = '</strong>';
}
else
{
// show page number 1, no link.
$html[] = '<strong>1</strong>';
}
echo implode('', $html);
Also note that the final ?> is not required in PHP files that do not have HTML code following the PHP code, so I left it off.
Buddy refer this URL
http://www.codediesel.com/php/simple-pagination-in-php/
OR
http://www.phpfreaks.com/tutorial/basic-pagination
Surely will help you.
Thanks

How To Split A Line From An Array Into Two Variables Using PHP

Here is the script as I am using it now:
<?php
echo '<html><body>';
// Data from a flat file
$dataArray = file('text.dat');
// Get the current page
if (isset($_REQUEST['page'])) {
$currentPage = $_REQUEST['page'];
} else {
$currentPage = 'some default value';
}
// Pagination settings
$perPage = 3;
$numPages = ceil(count($dataArray) / $perPage);
if(!$currentPage || $currentPage > $numPages)
$currentPage = 0;
$start = $currentPage * $perPage;
$end = ($currentPage * $perPage) + $perPage;
// Extract ones we need
foreach($dataArray AS $key => $val)
{
if($key >= $start && $key < $end)
$pagedData[] = $dataArray[$key];
}
foreach($pagedData AS $item)
echo ''. $item .'<br>';
if($currentPage > 0 && $currentPage < $numPages)
echo '« Previous page<br>';
if($numPages > $currentPage && ($currentPage + 1) < $numPages)
echo 'Next page »<br>';
echo '</body></html>';
?>
And here is the contents of text.dat
Fun
Games
Toys
Sports
Fishing
Pools
Boats
Now, my question is, What if text.dat looked like this?:
Fun||http://site.com/page11.html
Games||http://site.com/page12.html
Toys||http://site.com/page13.html
Sports||http://site.com/page16.html
Fishing||http://site.com/page18.html
Pools||http://site.com/page41.html
Boats||http://site.com/page91.html
I would like to know what to change in the script so I can basically do this instead:
foreach($pagedData AS $item1 and $item2)
echo ''. $item1 .'<br>';
Try:
foreach($pagedData AS $item) {
$item = explode('||', $item);
echo ''. $item[0] .'<br>';
}

Categories