Pagination. Select from x number of tables - php

i'm trying to make my second website using php and i'm stuck at some typical problem (i believe),
but very hard for me.
I'm making a page that show list of items depends on GET.
#1 if only "type" sended - show all items with x type.
#2 if only "tag" sended - show all items with x tag.
#3 if "type" and "tag" sended at the same time - show all items with x type and x tag.
problem #1 i solved this way
// items per page
$per_page = 5;
// 1) if isset type
if ( (isset($_GET['type'])) && (!isset($_GET['tag'])) ){
$type_id = get_safe_var($_GET['type']);
$con = mysql_connect(DB_HOST,DB_LOGIN,DB_PASSWORD) or die(mysql_error());
if ($con) {
mysql_select_db(DB_NAME) or die(mysql_error());
$sql = mysql_query("SELECT `item_type`, `item_type_name` FROM `item_types` WHERE `type_id` = '$type_id'");
$row = mysql_fetch_assoc($sql);
$type = $row['item_type'];
$type_name = $row['item_type_name'];
if ($type != ''){
$pages_query = mysql_query("SELECT COUNT(`id`) FROM `".$type."` WHERE `insearch` = '1'");
$number_of_pages = ceil( mysql_result($pages_query, 0) / $per_page );
$current_page = ( (isset($_GET['page'])) && ((int)$_GET['page'] > 0) ) ? (int)$_GET['page'] : 1;
$start = ($current_page - 1) * $per_page;
echo "<h1>$type_name</h1>";
$sql = mysql_query("SELECT `id`, `name`, `img` FROM `".$type."` WHERE `insearch` = '1' ORDER BY `id` DESC LIMIT $start, $per_page");
// echo items
while ($row = mysql_fetch_assoc($sql)){
$id = $row['id'];
$name = $row['name'];
$img = $row['img'];
echo "
<div id='items_cell'>
<img alt='$name' src='$img' width='145' height='200' /><br />
<a href='open_item.php?type=$type_id&id=$id'>$name</a><br />
<em>$type_name</em>
</div>";
}
}
mysql_close($con);
} else {echo 'sql connection error';}
}
pagination
// echo pagination
// 1) if isset type
if ( (isset($_GET['type'])) && (!isset($_GET['tag'])) ){
if ( (isset($number_of_pages)) && ($number_of_pages >= 1) && ($current_page <= $number_of_pages) ){
for ($i = 1; $i <= $number_of_pages; $i++){
if ($i == $current_page){
echo "<li><a href='?type=$type_id&page=$i' class='sel'>$i</a></li>";
} else {
echo "<li><a href='?type=$type_id&page=$i'>$i</a></li>";
}
}
}
}
I'm stuck at problem #2.
I got tag ID. Need to show all items with that tag.
I don't understand how to make a SELECT from x-number of tables with a working paginatin.
database structure -
Any help is welcome!
P.S. Maybe i need to change db structure to make SELECT easier?

You should definitely work on your table design. Having dynamic table names is a big NO-NO as you won't ever be able to do any useful joins. Just create one big tag-table and add a column type like you did in your table item_types.
To solve problems #1-#3 just build the WHERE-part of your query dynamically:
// empty selection
$where = array();
if (!empty($_GET["type"])
$where[] = "`item_type` = '".mysql_real_escape_string($_GET["type"])."'";
if (!empty($_GET["tag"])
$where[] = "`tag` = '".mysql_real_escape_string($_GET["tag"])."'";
$query = "SELECT ... FROM `item`"
// Join type-table
. " JOIN `item_types` ON `item`.`id` = `item_types`.`item_id`"
// Join all of this item's tags
. " JOIN `item_tags` ON `item`.`id` = `item_tags`.`item_id`"
// Filter tags by item_type
. " AND `item_types`.`item_type` = `item_tags`.`item_type`"
;
if (count($where) > 0)
$query .= "WHERE ".implode(" AND ", $where);

Related

Pagination (mysql+php) on results dependent on drop-down menu filters

I have this current query, and I am desperately trying to get the results paginated (total list - if no filters are applied by using the drop down menus is about 6000 rows), but don't know how. I've tried several tutorials already, but I keep getting my full list displayed, so the ceil() function never comes into play.
I think it is because my query isn't built to allow for a simple count on total rows in the query due to the pull down menus.
Can anyone help me build the pagination around this query?
$sql = "SELECT official_status, official_expiration_date, membership_status,membership_expiration_date, player_number, first_name, last_name, classification, gender, birth_year, rating, rating_effective_date, country, code, country.description, bracket.id, bracket.min, bracket.max, cutoff FROM Players, country, bracket, ratingscutoff WHERE membership_expiration_date >= cutoff AND Players.country = country.code ";
if (!empty($_GET['class'])) {
$filter_class = $_GET['class'];
$sql .= "AND classification = '{$filter_class}' ";
}
if (!empty($_GET['gender'])) {
$filter_gender = $_GET['gender'];
$sql .= "AND gender = '{$filter_gender}' ";
}
if (!empty($_GET['country'])) {
$filter_country = $_GET['country'];
$sql .= "AND country = '{$filter_country}' ";
}
if (empty($_GET['bracket'])) {
$filter_bracket = $_GET['bracket'];
$sql .= "AND bracket.id = '0' AND Players.birth_year BETWEEN bracket.min AND bracket.max ";
}
else
{
if (!empty($_GET['bracket'])) {
$filter_bracket = $_GET['bracket'];
$sql .= "AND bracket.id = '{$filter_bracket}' AND Players.birth_year BETWEEN bracket.min AND bracket.max ";
}
}
$sql .= "ORDER BY rating DESC, player_number ASC";
$result = mysqli_query($link, $sql) or die("Unable to select: ".mysqli_error());
$num_rows = mysqli_num_rows($result);
$counter = 1;
while ($row = mysqli_fetch_array($result)) {
printf("<tr>
<td class=\"stats\">$counter</td>
<td nowrap class=\"stats\"><b>%s %s <img src=\"/wp-content/uploads/2014/12/%s.png\" title=\"certified official until %s\"/></b>
</td>
<td class=\"stats\"><span title=\"current member through %s\">%s</span></td>
<td class=\"stats\"><span title=\"rating updated %s\">%s</span></td>
<td class=\"stats\">%s</td>
<td class=\"stats\">%s</td>
<td class=\"stats\">%s</td>
\n",
$row["player_number"], $row["first_name"], $row["last_name"], $row["official_status"], $row["official_expiration_date"], $row["membership_expiration_date"], $row["player_number"], $row["rating_effective_date"], $row["rating"], $row["classification"], $row["gender"], $row["description"]);
$counter++; //increment counter by 1 on every pass
}
For pagination, in most cases you need 2 queries, a first that counts the total number of rows, and the second that actually returns the rowset using a LIMIT with the last offset and the number of rows per page.
Basically the 2 queries are the same, the first one being just a COUNT(). Run it, to get the total (I set it in a $num_rows variable in my example), then set a variable to have your number of rows per page (let's say $rows_per_page = 10;), and then before the scond query, do something like:
if (empty($_GET['page'])) {
$page = 1;
$offset = $rows_per_page;
} else {
$num_pages = floor($num_rows / $rows_per_page);
if ($_GET['page'] > $num_pages) {
$page = $num_pages;
} else {
$page = $_GET['page'];
}
$offset = $rows_per_page * $page;
}
You have your limits now for the second query:
LIMIT '.$offset.', '.$rows_per_page
UPDATE: I quickly wrote something using your code, it should work with minor changes (not tested)
$rows_per_page = 10;
$sql_count = "
SELECT
COUNT(*)
FROM
Players, country, bracket, ratingscutoff
WHERE membership_expiration_date >= cutoff
AND Players.country = country.code
";
$result_count = mysqli_query($link, $sql_count) or die("Unable to select: ".mysqli_error());
$num_rows = mysqli_num_rows($result_count);
if (empty($_GET['page'])) {
$page = 1;
$offset = $rows_per_page;
} else {
$num_pages = floor($num_rows / $rows_per_page);
if ($_GET['page'] > $num_pages) {
$page = $num_pages;
} else {
$page = $_GET['page'];
}
$offset = $rows_per_page * $page;
}
// Your other filters are being omitted for more clarity
$sql_select = "
SELECT
official_status, official_expiration_date, membership_status,membership_expiration_date, player_number, first_name, last_name, classification, gender, birth_year, rating, rating_effective_date, country, code, country.description, bracket.id, bracket.min, bracket.max, cutoff
FROM
Players, country, bracket, ratingscutoff
WHERE membership_expiration_date >= cutoff
AND Players.country = country.code
ORDER BY rating DESC, player_number ASC
LIMIT ".$offset.", ".$rows_per_page."
";
$result = mysqli_query($link, $sql_select) or die("Unable to select: ".mysqli_error());

SQL query issues: [1] Count(*) and [2] using NOT vs <>

I have been staring at this code so long it is starting to bleed together. So let's get a couple things out of the way:
I am a low-moderate level SQL user and am still learning the best ways to accomplish queries and such
I have been building a PHP based quote-generator tool that ties in with an SQL database
Now, here is what I am trying to accomplish:
I would like to have pagination with the results of quotes that have been created with a status that is NOT "Dead", "Duplicate", or "Signed" and the ID does NOT equal 999 (because I wanted the quotes to jump to 1000 and I did not build the database correctly at first)
Here is what I have accomplished:
I was able to create the basic structure and it works just fine on page 1... then it all goes sideways. I was thinking that it was something to do with my count(*) query, but that seems fine - well functional, at least:
$countQry = "SELECT COUNT(*)
from needsassessment
WHERE ID <> 999
AND status <> 'Dead'
AND status <> 'Duplicate'
AND status <> 'Signed'";
$countResult = $mysqli->query($countQry);
while($rowQ = mysqli_fetch_array($countResult)) {
$totalRows = $rowQ[0];
$each = ceil($totalRows/$limit);
$where = "WHERE ID > 0";
if ($totalRows == 0) {
echo "You have not created any quotes.";
}
}
$limit = 15;
if (isset($_GET['q']) && $_GET['q'] !== "") {
$offset = $_GET['q'];
} else {
$offset = 0;
}
$query = "SELECT * FROM needsassessment $where
where $and
AND ID <> 999
AND NOT status = 'Dead'
AND NOT status = 'Duplicate'
AND NOT status = 'Signed'
ORDER BY ID DESC LIMIT $offset, $limit";
$result = $mysqli->query($query);
$row_cnt = mysqli_num_rows($result);
if ($row_cnt == 0) {
echo "You have not created any quotes."; die;
}
if (!isset($each)) {
$each = $row_cnt/$limit;
}
if ($each > 1) {
echo "<ul class='pagination'>";
for($i=1,$y=0;$i<=$each,$y<=($each-1);$i++,$y++) {
echo "<li><a";
if ($offset == ($y*15)) {echo ' class="active"';}
echo " href='?q=".($y*15)."'>$i</a></li>";
}
echo "</ul>";
}
Okay, so here are my questions:
I saw someone say that using PHP's mysqli_num_rows() is wrong and
that I should use SQL's COUNT(*). Why? Does it have a different result or take longer?
What is going on with page's
2 and 3? When I do a row count it says it sees 15 rows but only some
are showing. I have some records (i.e. those with a status of
"Signed" or "Dead") that are excluded from this list and I was
thinking that may have been the issue, but it doesn't seem to matter
on the first page.
What is the difference - if there is one -
between "NOT" and "<>" for checking records?
If you have any suggestions or if I have done anything blatantly wrong or inefficiently please let me know so I can correct it :)
Thanks to all that make Stack Overflow AWESOME!
EDIT:
There certainly was some code missing:
if (!isset($sst)) {
$where = "";
$sst = "";
$countQry = "SELECT COUNT(*) from needsassessment WHERE ID <> 999 AND status <> 'Dead' AND status <> 'Duplicate' AND status <> 'Signed'";
$countResult = $mysqli->query($countQry);
while($rowQ = mysqli_fetch_array($countResult)) {
$totalRows = $rowQ[0];
$each = ceil($totalRows/$limit);
$where = "WHERE ID > 0";
if ($totalRows == 0) {echo "You have not created any quotes.";}
}
}
else {
if ($option !== "*") {
$where = "WHERE ".$option." LIKE '%".$sst."%'";
}
if ($option == "*") {
$where = "WHERE status LIKE '%".$sst."%' OR title LIKE '%".$sst."%' OR propType LIKE '%".$sst."%' OR pSType LIKE '%".$sst."%' OR createDate LIKE '%".$sst."%'";
}
$offset = 0;
}
if ($_SESSION['admin'] >= 1) {
$and = "";
}
else {
$and = "AND creatorID = '".$_SESSION['user']."'";
}

I'm trying to pull data from database where the data will be pulled from two different tables in the db,error is in $returns = mysql_query

I'm trying to pull data from two different tables in the database and I keep on having error. when I run the code it displays nothing
Here is my code:
<?php
$st="";
$sc="";
if (isset($_POST['submit']) && $_POST['submit'] == "submit"){
$st=$_POST['s-t'];
$sc= "WHERE nums like \"%$st%\" or d_n like \"%st%\" ";
}
if (isset ($_GET['look']) && $_GET ['look'] != "") {
$st=$_GET['look'];
$sc = "WHERE nums like \"%$st%\" or d_n like \"%st%\" ";
}
$db = mysql_db_connect();
$rpp = 50;
if (isset($_GET['page'])){
$pn = $_GET['page'];
$begin = ($rpp*$pn)-$rpp;
$finish=($rpp*$pn);
$finish=50;
}
else {
$pn =1;
$begin = 0;
$finish =$rpp;
}
$returns = mysql_query ("SELECT * FROM extenz $sc", $db);
$numer_rows = mysql_num_rows($returns);
$number_pages = ((int) ($numer_rows/$rpp)) +1;
if (($number_rows % rpp) ==0){
$number_pages=$number_pages -1;
}
$returns = mysql_query("SELECT nums, name , p_m FROM extenz, P_exten left join p_exten on extenz $sc order by nums & P_m LIMIT $begin, $finish", $db);
?>
i answered my question
the error was in the following line of code
$returns = mysql_query("SELECT nums, name , p_m FROM extenz, P_exten left join p_exten on extenz $sc order by nums & P_m LIMIT $begin, $finish", $db);
and the correction was
$returns = mysql_query("SELECT extenz.nums, extenz.name,p_exten.P_M FROM extenz LEFT JOIN ON p_exten.extenz=extenz.nums $sc ORDER BY nums LIMIT $begin, $finish",$db);

Pagination Php not working when different sql query conditions are added

Hello I am facing a problem with my pagination system, where if I list results from a mysql table it is working fine, but in case If I add some conditions inside the SQL Query like "AND" this column "AND" other column the script shows the results properly on the first page, when I chooce the second page instead of showing the second portion of results from 26 forward it is starting a new pagination and it is showing everything from the begining without the contions added inside the query. Here is the code of the pagination with the query:
//This gets all the other information from the form
$ciudad=$_POST['ciudad'];
$tipo=$_POST['tipo'];
$con=mysqli_connect();
// Check connection
$sql = "SELECT * FROM cursos WHERE 1";
if (!empty($ciudad)) {
$sql .= " AND ciudad = '$ciudad' ";
}
if (!empty($tipo)) {
$sql .= " AND tipo= '$tipo' ";
}
if (!$result = mysqli_query($con,$sql))
{
die("Error: " . mysqli_error($con));
}
$per_page =25;//define how many games for a page
$count = mysqli_num_rows($result);
$pages = ceil($count/$per_page);
if(!isset($_GET['page']) || $_GET['page']=="") {
$page="1";
} else {
$page=$_GET['page'];
}
$start = ($page - 1) * $per_page;
$sql = "SELECT * FROM cursos WHERE 1 LIMIT $start,$per_page";
?>
This is the code of the generated pages links:
<?php
//Show page links
for ($i = 1; $i <= $pages; $i++)
{?>
<li id="<?php echo $i;?>"><?php echo $i;?></li>
<?php
}
?>
The 2 problems where:
additional filter are not anymore selected in the next page ($_POST will be empty)
instructions related to pagination where calculated AFTER the query (which, obviously, couldn't use theses parameters)
You can either store your extra queries conditions in session, or add it as parameter in the "next page link", or transform your link to a submit form (which is probably the best option)
<li id="<?php echo $i;?>"><?php echo $i;?></li>
If you choose the link solution, don't forget to change your _POST in _GET (or check the second if the first is empty, or use $_REQUEST)
I have to mention your code is not sql injection free and using mysqli_prepare() may worth the time (for security and performances)
EDIT: so, here we go:
sidenotes: using $_REQUEST is not always recommended
And I noticed also you execute your query BEFORE using the pagination system...
//This gets all the other information from the form
$ciudad=$_REQUEST['ciudad'];
$tipo=$_REQUEST['tipo'];
$con=mysqli_connect();
// Check connection
$sql = "SELECT * FROM cursos WHERE 1";
if (!empty($ciudad)) {
$sql .= " AND ciudad = '$ciudad' ";
}
if (!empty($tipo)) {
$sql .= " AND tipo= '$tipo' ";
}
// PAGINATION MOVED UP
$per_page =25;//define how many games for a page
$count = mysqli_num_rows($result);
$pages = ceil($count/$per_page);
if(empty($_GET['page'])) {
$page="1";
} else {
$page=$_GET['page'];
}
$start = ($page - 1) * $per_page;
$sql .= ' LIMIT '.$start.','.$per_page;
if (!$result = mysqli_query($con,$sql))
{
die("Error: " . mysqli_error($con));
}
//Show page links
for ($i = 1; $i <= $pages; $i++)
{?>
<li id="<?php echo $i;?>"><?php echo $i;?></li>
<?php
}
?>
If $ciudad and $tipo both are not empty your query on execution will look like this:
SELECT * FROM cursos WHERE 1 AND ciudad = '$ciudad' ORDER BY id DESC AND tipo= '$tipo' ORDER BY id DESC
It should be like this if i am not mistaken:
SELECT * FROM cursos WHERE 1 AND ciudad = '$ciudad' AND tipo= '$tipo' ORDER BY id DESC
What I would do is change this:
$sql = "SELECT * FROM cursos WHERE 1";
if (!empty($ciudad)) {
$sql .= " AND ciudad = '$ciudad' ORDER BY id DESC ";
}
if (!empty($tipo)) {
$sql .= " AND tipo= '$tipo' ORDER BY id DESC ";
}
too this:
$sql = "SELECT * FROM cursos WHERE 1 ";
if (!empty($ciudad)) {
$sql .= "AND ciudad= '$ciudad' ";
if (!empty($tipo)) {
$sql .= "AND tipo= '$tipo' ";
}
$sql .= "ORDER BY id DESC ";
}
I've also got a link which might help you out with the pagination.
http://www.phpjabbers.com/php--mysql-select-data-and-split-on-pages-php25.html
If city and type are set then your SQL will have two instances of order by... You should add order by after the if statements.

Display entries from a database, list them from newest to oldest and stop after a certain amount?

I have the following tables in my DB:
id
title
heading
content
date
tags
username
like
dislike
comments
I have the database hooked up so that it will show what's in the rows, but I don't know how to make it so that it will generate and list a "post block" every time a new entry is made. I would also like to list them from newest posts to oldest, all while limiting the posts to 10-20 per page.
<?php
$connect = mysql_connect('localhost','root','','andrewryan') or die('error connection');
mysql_select_db('andrewryan');
$query = "Select * FROM entry";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
$username = $row['username'];
$title = $row['title'];
$heading = $row['heading'];
$content = $row['content'];
$tags = $row['tags'];
$like = $row['like'];
$dislike = $row['dislike'];
$comment = $row['comment'];
$date = $row['date'];
?>
I also have another page with just one block of html. Which is the post framework with all the variables given where they are needed. Any reference for what I'm going for can be found at this link if it helps: HERE
As far as the query:
// Tildes on date since it is a keyword and some databases will error out without them
// Order by date is if you are using a compatible storing: unix timestamp or DateTime field
$query = "Select * FROM entry ORDER BY `date` DESC";
$result = mysql_query($query);
$rowCount = 0;
while($row = mysql_fetch_array($result)) {
$username[$rowCount] = $row['username'];
$title[$rowCount] = $row['title'];
$heading[$rowCount] = $row['heading'];
$content[$rowCount] = $row['content'];
$tags[$rowCount] = $row['tags'];
$like[$rowCount] = $row['like'];
$dislike[$rowCount] = $row['dislike'];
$comment[$rowCount] = $row['comment'];
$date[$rowCount] = $row['date'];
$rowCount++;
}
This is as far as showing the posts:
// limit is used to show the max posts per page.
$limit = 20;
//The following for is for paging
for($i = 1; $i <= $numofpages; $i++){
if($i == $page){
echo $i . " ";
}else{
echo "<a href='page.php?page=" . $i . "'>" . $i . "</a> ";
}
}
// The following is to show your post blocks
for($j = 0; $j < $limit; $j++){
//This will give you the appropriate post for the page
$temp = $j + (($page * $limit) - $limit);
// Your code to show your post blocks
echo $username[$temp]; //For example, just format for your site layout.
}
SELECT all the fields that you are interested to fetch.
Use DATE_FORMAT function to format the date field and assign to a new alias.I named it ndate.
Then ORDER BY ndate
SELECT username,title,heading,content,tags,like,dislike,comment,DATE_FORMAT(date, '%d-%M-%Y') AS ndate FROM entry ORDER BY ndate
fetch the date as $row['ndate']

Categories