I am trying to figure out how I can update my sql query dynamically.
On the main page, I have a pagination script that counts how many pages there will be:
<?php
function generate_pagination($sql) {
include_once('config.php');
$per_page = 3;
//Calculating no of pages
$result = mysql_query($sql);
$count = mysql_num_rows($result);
$pages = ceil($count/$per_page);
//Pagination Numbers
for($i=1; $i<=$pages; $i++)
{
echo '<li class="page_numbers" id="'.$i.'">'.$i.'</li>';
}
}
?>
I then have in the body of the same page this line of code to populate the page numbers:
<?php generate_pagination("SELECT * FROM explore WHERE category='marketing'"); ?>
So, that line is displaying the necessary amount of page numbers to be displayed for just the 'marketing' category.
The problem that I am having is with that single line of code. I want to make the category dynamic, so instead of it being hardcoded to 'marketing' I would like jquery to get the id of an element and place it in.
The element would be this link that I have on the same page:
Marketing
So, when the user clicks that link, I am trying to place the id of the link in the category section of the query using jquery.
I hope that made sense, and if anyone can assist me on this that would be great.
First, the PHP side:
<?php
function generate_pagination($sql) {
include_once('config.php');
$per_page = 3;
//Calculating no of pages
$result = mysql_query($sql);
$count = mysql_num_rows($result);
$pages = ceil($count/$per_page);
//Pagination Numbers
for($i=1; $i<=$pages; $i++)
{
echo '<li class="page_numbers" id="'.$i.'">'.$i.'</li>';
}
}
?>
<?php generate_pagination("SELECT * FROM explore WHERE category='" . mysql_real_escape_string ( $_POST ['category'] ) . "'"); ?>
Then in your jquery post:
$("a.category").click(function() {
$.post("test.php", { category: $(this).attr("id") },
function(data){
//Load your results into the page
});
});
On click we take the ID, pass it to the server as a post variable category, then on the server, grab it, escape it properly for security, and use that query. Load your results the same way you are now, that part doesn't change.
Related
I am writing PHP script to display data from the database (Mysql) on my webpage. I don't want all the information to display on a single page to avoid scrolling. However, I want to display only a few and then use page numbers to navigate to the rest. I managed to create the page numbers and yet still all the information is showing on a single page. Below is my code:
<?php
include('./includes/DB_Config.php');
$status = 1;
// Set number of Post per page for navigation
$post_per_page = 2;
if (isset($_GET['page']))
{
$startP = ($_GET['page'] - 1) * $post_per_page;
}
else
{
$startP = 0;
}
$post = mysqli_query ($mySQL_Conn, "SELECT * FROM BlogPost WHERE status = '$status'");
// Fetch Data or number of rows
$dataRw = mysqli_num_rows($post);
$pages = $dataRw / $post_per_page;
if ($dataRw == 0)
{
$_SESSION['NoPost'] = "No Post Found!";
}
else
{
unset($_SESSION['NoPost']);
//$pages = ceil($dataRw / $rows_per_page);
//$pages = array_slice($dataRw, $startP, $post_per_page);
while ($data = mysqli_fetch_array($post)) //Fetch data in array
{
//Assign data to variabes
$name = $data['blogger_Name'];
$postDate = $data['dateTime'];
$blogpost = $data['blog_message'];
$date = strtotime($postDate);
?>
<p> <span><?php echo $_SESSION['NoPost'] ; ?> </span></p>
<p> <span>By:</span><?php echo $name; ?> </p>
<p> <span>Posted On: </span> <?php echo date("j F Y", $date); ?> </p>
<p> <span>Post: </span><?php echo $blogpost; ?> </p>
<?php
}
}
?>
<hr>
<?php
for ($currentpage = 0; $currentpage < $pages; $currentpage++ )
{
?>
<span> <?php echo $currentpage + 1; ?> </span>
<?php
}
?>
What you are trying to accomplish is a very common pattern, and it's called pagination.
You can use LIMIT and OFFSET in your mysql queries to get only a certain subset of the data, and you can use this for basic pagination.
For example, if you want to display 50 results per page, and the user is on the third page, you set LIMIT to 50 and OFFSET to 2*50 (100), keep in mind the first page is an offset of 0 so we subtract the page by one.
You can use the following sql query to get a subset of data for a specific page.
"SELECT * FROM Users LIMIT $num_results OFFSET ".(($page_num-1)*$num_results);
You can get the total number of possible pages by getting the total row count from the Users table and dividing it by $num_results. A good idea might be to have your output script take a GET url query parameter that will be used as the page number.
I'm using this while statement to show all contents of database...
$sql = mysql_query("SELECT id,question,date,user,numberofcomments,body,locked FROM questions ORDER BY id DESC");
while($row=mysql_fetch_assoc($sql)) {
echo '<div class="comment">';
echo '<div class="leftpart">';
echo "<div class='date'><img src='../assets/icons/Time-info.png'> ".ago($row['date']);
echo "</div><br><img src='../assets/icons/User-Info.png'> ".$row['user'];
echo "<br><img src='../assets/icons/Comments.png'> ".$row[numberofcomments];
echo '</div>';
echo '<div class="rightpart-topic">';
if($row['locked']==1) { echo '<img src="../assets/icons/Lock.png" /> ';
}
echo ''.$row['question'].'';
echo '<br>'.substr($row['body'],0,70).'...';
echo '</div>';
echo '</div>';
}
I want to show only 10 rows then have links to show the rest (as in page 1,2,3,4, last type thing). How would I go about doing that? It would help if you could also explain your code as it would be greatly appreciated. It helps my learning process.
Thanks!
You need to do a LIMIT in your query using some sort of passed $_GET variable.
$start=0;
$limit = 10;
$page = (isset($_GET['page']) ? : 0));
$start = $page * $limit;
$sql = mysql_query("SELECT id,question,date,user,numberofcomments,body,locked FROM questions ORDER BY id DESC LIMIT {$start},{$limit}");
Should be pretty self explanatory.
If there is not page variable set then you are viewing page 0, or the first 10 results of your database query. If page = 1 then you are going to be viewing $page (value=1) * $limit (10) = $start (now value of 10), which will give you results 10-20 or page 1. etc.
So provide your user a button which can link them to a hard paginated link, or do it ajax.
Each url will need to be like so:
http://wwww.yoursite.com/somepage.php?page=1
Efficiency aside, you could simply set a counter and check if it value Is greater than 10 during the loop. If so, add a 'hidden' class to the parent div. That class would use display:none;
I have a table that pulls tickets from a MYSQL database and displays them to the user. This part works wonderfully! But, once the user gets 5-10 tickets, the page becomes long and ugly. I am wanting to paginate the responses automatically to show maybe 5 tickets per page and show the rest on following pages.
I am using Bootstrap and have the following for the display of the pagination. "Although I fear this is only pseudo code" I added id's to each main element.
<ul class="pager" id="pagerUL">
<li class="previous" id="previousUL">
← Previous
</li>
<li class="next" id="nextUL">
Next →
</li>
</ul>
Essentially the only code used to pull the database information on the page is:
<?php if(count($tickets) > 0) : ?>
<?php foreach ($tickets as $ticket): ?>
//table content
<?php endforeach ?>
<?php else : ?>
<tr>
<td colspan="7">No Tickets Created.</td>
</tr>
<?php endif; ?>
I thought we could add something to the <?php if(count($tickets) > 0) : ?> But honestly, I am not sure as I am not a expert at php and never even attempted or had the need to build pagination up until now. Any help, guidance, thoughts would be appreciated.
Pass the page number thru the URL and then grab it via php with $_GET.
$page = $_GET['page'];
$per_page = 10; // Define it as you please
$start = $page*$per_page;
$query = "SELECT * FROM table LIMIT ".$start.", ".$per_page;
$result = mysql_query($query);
$count = mysql_num_rows($result);
$i = 0;
for($i=0;$i<$count;$i++)
{
//echo out what you want
echo "";
}
$total_pages = ceil($count/$per_page);
for($i=0;$i<$total_pages;$i++)
{
if($page != $i)
{
echo "<a href='/page.php?page=".$i."'>".$i."</a>";
} else
{
echo $i;
}
}
I am not a well-versed programmer so i don't want to use a complicated pagination. Is there an alternative to using a pagination like in my queries can i limit them to say 20 results and then if their are more than 20 results i can show a "next" button and then that button will further load the next results??
I only want "next" to show if there are 20> results? Any help will be appreciated. Thanks.
Code:
$query="SELECT * FROM actresses where actress_id = '$actressid' and production_full_name LIKE '%$q%'";
$result=mysql_query($query);
$num=mysql_numrows($result);
mysql_close();
echo "";
$i=0;
while ($i < $num) {
$1=mysql_result($result,$i,"production_full_name");
$2=mysql_result($result,$i,"production_id");
$3=mysql_result($result,$i,"actress");
echo "<br><div id=linkcontain><a id=slink href=$data/actress.php?id=$2>$3</a><div id=production>$1</div></div>";
echo "";
$i++;
}
You could add a limit to your query.
$lower_limit = $results_per_page * $page_number;
$upper_limit = $lower_limit + $results_per_page
..and production_full_name LIKE '%$q%' LIMIT $lower_limit, $upper_limit
Then make a conditional "next page" link
if ($upper_limit > 20) echo 'Next;
You can find many examples searching on google.
http://www.php-mysql-tutorial.com/wikis/php-tutorial/paging-using-php.aspx for example.
You only have to edit $rowsPerPage for amount of results, and if you want further edit on what to get from the DB, the $query.
Includes are not necessary, though.
edit: note the implication of using a $_GET that will have influence on the DB query. You have to be careful to not allow dangerous values in it (mysql injection). In the example of the webpage, it uses ceil, so I believe that it will output 0 for a non numeric value, which is safer.
You can use the PEAR packages.
They are much easier to use similar to the frameworks.
But before you use them you need to check whether the PEAR works on your server or not.
If you are using it locally then there are steps to install the PEAR packages on your local machine. For more instructions to install PEAR.
Click here to view the installation steps.
Once you have installed the PEAR package please follow the instruction to configure the PAGER class.http://www.codediesel.com/php/simple-pagination-in-php/
J
Something like that:
$data = mysql_query("SELECT * FROM `table`");
$total_data = mysql_num_rows($data);
$step = 30;
$from = $_GET['p'];
$data = mysql_query("SELECT * FROM `table` LIMIT '.$from.','.$step.'"
And creating links:
$p=1;
for ($j = 0 ; $j <= $total_data+$step; $j+=$step)
{
echo ' '.$p.' ';
$p++;
} ?>
Not tested.
If your query is set up as
"SELECT SQL_CALC_FOUND_ROWS * FROM actresses where actress_id = '$actressid' and production_full_name LIKE '%$q%' LIMIT ".($page*$lpage).",".$lpage
... the next statement can be SELECT FOUND_ROWS() to get the actual number of results.
Don't forget to put mysql_real_escape_string() on those variables.
NEVER use SELECT * with mysql_num_rows; if it's a big table, it will waste a LOT of time.
What you can do is fetch a COUNT(*) of how many rows are in your set of data. Then decide how many items you want per page. $numberOfRows / $itemsPerPage gives you the number of pages. In MySQL, to limit results you use LIMIT X, Y X is the beginning of the range, and Y is the number of items you want to fetch. So to fetch all the items on a page, your query would be LIMIT ($currentPage * $itemsPerPage), $itemsPerPage Then it's up to you, depending on how you want to format your pagination, to write the view logic. Just go from back to front: if the current page is 1, then the previous button is disabled. If the page is not 1, then the current page number is the number of pages from the beginning. If the total number of pages is bigger than the current page, then count from the current page, until the last page (unless you want to cut off the page count at some point)
I use the following method to assist in creating a list of pages, no matter what direction. I could plug in 5 for the current page, and 0 as the goal page, and it would return a list of 5 pages for me to iterate through, in order.
/*
* Generates a list of pages based on the current page to the goal page number
*/
function generatePageList($currentPage, $goal) {
$span = $goal - $currentPage;
$step = abs($span) / $span;
$list = array();
for($x = $currentPage; $x !== $goal;) {
// We want to add the step at the beginning of the loop, instead of
// at the end
// Fixes bug when there are only two pages
$x += $step;
$list[] = $x;
}
return $list;
}
This is more easy way to create pagination of a data
<?php
require_once 'db_connect.php';
$limit = 20;
if (isset($_GET["page"])) { $page = $_GET["page"]; } else { $page=1; };
$start_from = ($page-1) * $limit;
$sql = "SELECT * FROM employee ORDER BY id ASC LIMIT $start_from, $limit";
$rs_result = mysqli_query($con, $sql);
?>
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Salary</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_assoc($rs_result)) {?>
<tr>
<td><?php echo $row["employee_name"]; ?></td>
<td><?php echo $row["employee_salary"]; ?></td>
<td><?php echo $row["employee_age"]; ?></td>
</tr>
<?php
};
?>
</tbody>
</table>
<?php
$sql = "SELECT COUNT(id) FROM employee";
$rs_result = mysqli_query($con, $sql);
$row = mysqli_fetch_row($rs_result);
$total_records = $row[0];
$total_pages = ceil($total_records / $limit);
$pagLink = "<nav><ul class='pagination'>";
for ($i=1; $i<=$total_pages; $i++){
$pagLink .= "<li><a href='index.php?page=".$i."'>".$i."</a></li>";
};
echo $pagLink . "</ul></nav>";
?>
<script type="text/javascript">
$(document).ready(function(){
$('.pagination').pagination({
items: <?php echo $total_records;?>,
itemsOnPage: <?php echo $limit;?>,
cssStyle: 'light-theme',
currentPage : <?php echo $page;?>,
hrefTextPrefix : 'index.php?page='
});
});
</script>
Hey, I am still trying to allow multiple filters to be selected for my pagination script but not sure how to do it being very new to php and programing in general.
So in my pagination, when a user clicks the 'marketing' button(link) it queries the database just for the category that = marketing. The same goes for the other 2 filter buttons as seen in the script below. (automotive, sports).
The problem is, I want to be able to select multiple filters like only marketing and auomotive or automotive and sports, for example if I click the marketing filter and then the automotive, it would display the categories that equal marketing, and automotive.
I have no idea how to accomplish this, so I have come to the experts to help me out.
This is the script I am working on:
<h3>Filter results by:</h3>
<a href='pagi_test.php?category=marketing'>marketing</a>
<a href='pagi_test.php?category=automotive'>automotive</a>
<a href='pagi_test.php?category=sports'>sports</a>
<br />
<h3>Results:</h3>
<?php
//connecting to the database
$error = "Could not connect to the database";
mysql_connect('localhost','root','root') or die($error);
mysql_select_db('ajax_demo') or die($error);
//max displayed per page
$per_page = 3;
//get start variable
$start = $_GET['start'];
$category = mysql_real_escape_string($_GET['category']);
//count records
$record_count = mysql_num_rows(mysql_query("SELECT * FROM explore WHERE category='$category'"));
//count max pages
$max_pages = $record_count / $per_page; //may come out as decimal
if (!$start)
$start = 0;
//display data
$get = mysql_query("SELECT * FROM explore WHERE category='$category' LIMIT $start, $per_page");
?>
<table width="800px">
<?php
while ($row = mysql_fetch_assoc($get))
{
// get data
$id = $row['id'];
$site_name = $row['site_name'];
$site_description = $row['site_description'];
?>
<tr>
<td><?php echo $id; ?></td>
<td><?php echo $site_name; ?></td>
<td><?php echo $site_description; ?></td>
</tr>
<?php
}
//setup prev and next variables
$prev = $start - $per_page;
$next = $start + $per_page;
//show prev button
if (!($start<=0))
echo "<a href='pagi_test.php?category=$category&start=$prev'>Prev</a> ";
//show page numbers
//set variable for first page
$i=1;
for ($x=0;$x<$record_count;$x=$x+$per_page)
{
if ($start!=$x)
echo " <a href='pagi_test.php?category=$category&start=$x'>$i</a> ";
else
echo " <a href='pagi_test.php?category=$category&start=$x'><b>$i</b></a> ";
$i++;
}
//show next button
if (!($start>=$record_count-$per_page))
echo " <a href='pagi_test.php?category=$category&start=$next'>Next</a>";
?>
Any help on this would be great. Thank you.
-- EDIT --
If anyone has a better method of doing a pagination system with multiple filters than the one above, please let me know.
While selecting second filter u can add the category
ex:
At first ur variable $category has
$category="Marketing";
When user filter with another category suppose automotive then add it to $category with a delimeter,Now
$category="Marketing:Automotive";
when u access thru GET use explode:
$cat=explode(":",$_GET['category']);
and write your condition
$condition="category=category[0]";
for($i=1; $i<sizeof($cat); $i++)
{
$condition="AND category=$cat[$i]";
}
$where="WHERE $condition";
use $where in ur query, like
$record_count = mysql_num_rows(mysql_query("SELECT * FROM explore $where"));
I see two separate issues
How to allow the user to select more than one category to filter by
How to propagate those choices to the pagination links
Each for which I have a solution!
How to allow the user to select more than one category to filter by
A form is going to be the most direct approach.
<h3>Filter results by:</h3>
<form action="pagi_test.php" method="GET">
<input type="checkbox" name="category[]" value="marketing" id="cat_marketing"/>
<label for="cat_marketing">Marketing</label>
<br/>
<input type="checkbox" name="category[]" value="automotive" id="cat_automotive"/>
<label for="cat_automotive">Automotive</label>
<br/>
<input type="checkbox" name="category[]" value="sports" id="cat_sports"/>
<label for="cat_sports">Marketing</label>
<br/>
<input type="submit" value="Filter!" />
</form>
Now, $_GET['category'] will be an array of every category that was selected.
$categories = $_GET['category'];
$inClause = "'" . implode( "','", array_map( 'mysql_real_escape_string', $categories ) ) . "'";
//count records
$record_count = mysql_num_rows(
mysql_query( "SELECT * FROM explore WHERE category IN($inClause)" )
);
Of course, you'd probably want to add a check here to make sure $categories isn't empty before you execute the query.
You'll need to modify the actual selection query as well
//display data
$get = mysql_query("SELECT * FROM explore WHERE category IN($inClause) LIMIT $start, $per_page");
Bingo! Now that part is done!
How to propagate those choices to the pagination links
Since we already have an array of the categories selected stored in $categories, this will be trivial using http_build_query().
//setup prev and next variables
$prev = $start - $per_page;
$next = $start + $per_page;
// Get the categories in an HTML-safe array
$requestVars = array_map( 'htmlspecialchars', $categories );
//show prev button
if (!($start<=0))
{
$requestVars['start'] = $prev;
echo 'Prev ';
}
//show page numbers
//set variable for first page
$i=1;
for ( $x = 0; $x < $record_count; $x = $x + $per_page )
{
$requestVars['start'] = $x;
if ( $start != $x )
{
echo ''. $i .' ';
} else {
echo '<b>'. $i .'</b> ';
}
$i++;
}
//show next button
if (!($start>=$record_count-$per_page))
{
$requestVars['start'] = $next;
echo 'Next ';
}
Now, there are still holes in this implementation.
Since the <form> is printed to the page before the rest of the logic, there's no way to pre-select the checkboxes that represent the current filter choices. Which you could definitely change.
Also, you have categories as literal strings in the PHP script - they would really be better in their own table in the database.
The way you retrieve a count for the entire data set is inefficient - it sends the entire data set over the wire to PHP, which then is responsible for determining the record count. It's much better to run a separate query that uses SELECT count(*) ... instead.