Need little help with Mysql paging (LIMIT) - php

I have this code:
$page = $_GET['page'];
$res_per_page = $_GET['res_per_page'];
$start_point = (($page * $res_per_page) - $res_per_page);
$query.= " LIMIT $start_point, $res_per_page";
$qry_result = mysql_query($query) or die(mysql_error());
$total_pages = ceil($nr_ads / $res_per_page);
The variable '$nr_ads' is the total nr of ads...
The code works fine, but I wonder how I can figure out which ads are showing, ex:
Showing ads 10 - 20
Thanks...

print 'Showing ads ' . $start_point . ' - ' . min($nr_ads, $start_point + res_per_page);
Basically you've already got you starting point (which is given to your LIMIT clause in the SQL. The "end point" is calculated by adding $res_pre_page to this starting point. On the last page, however, you may only have 2 records - therefore you should use the min() function to print e.g. "Showing ad 60 - 62".
Follow up: Another answer mentions the risk of SQL injection. You'll be safe by using:
$page = intval($_GET['page']);
$res_per_page = max(1, intval($_GET['res_per_page'])); // To avoid division by zero :)

The simplest way would be to create an ID field in your table and use that to display the information you want, your query would be modified like so:
LIMIT $start_point, $res_per_page ORDER BY ad_id ASC
from there, you can get the first result and the last result and use it to output the information you are gathering.
One very important security note the following code can cause remote SQL injection:
$query.= " LIMIT $start_point, $res_per_page";
It is highly recomended you change it to:
$query.= " LIMIT $start_point, ".mysql_real_escape_string($res_per_page)." ORDER BY ad_id ASC";

Related

Server-side processing Datatables pagination Microsoft SQL

Im trying to setup pagination with datatables using PHP PDO with MS SQL, since "limit" is not applicable i find it really hard to make the code work.
I have tried the "TOP" syntax but it will only filter the specified number and the pagination wont work.
I have tried offset and fetch still not working.
These is the working code when Mysql is used and its so easy to understand and perform.
if($_POST["length"] != -1)
{
$query .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
}
These are the codes i tried (sorry im not really great in coding) :
//if($_POST["length"] != -1)
{
Trial 1 : //$query .= "TOP " . $_POST['start'] . " OFFSET " . $_POST['length'];
Trial 2 : //$query .= "SELECT * from item ORDER BY id DESC offset 0 rows fetch next 10 rows only ";
Trial 3 ://$query .="AND id BETWEEN ".intval( $_POST["start"] )." AND ".intval( $_POST["length"] );" "
}
The result should be a pagination with 10 filtered records each.enter image description here
Update 1:
Here is the screenshot of the query i tried to test it in a MS SQL server but getting an error (using MS SQL 2008)
SQL Query
Your approach depends on SQL Server version.
Approach, based on ORDER BY clause with OFFSET and FETCH as a paging solution requires SQL Server 2012+. Your syntax seems correct, so next code should work:
<?php
if ($_POST["length"] != -1) {
$query = "
SELECT *
FROM item
ORDER BY id DESC OFFSET ".($_POST['start']-1)." ROWS FETCH NEXT ".$_POST["length"]." ROWS ONLY
";
}
?>
For SQL Server 2008+, you may use ROW_NUMBER() as a paging solution:
<?php
if ($_POST["length"] != -1) {
$query =
"SELECT *
FROM (
SELECT
*,
ROW_NUMBER() OVER (ORDER BY id DESC) AS Rn
FROM item
)
WHERE Rn BETWEEN ".$_POST['start']." AND ".($_POST['start'] + $_POST['length'] - 1);
}
?>
In MSSQL to use the limit you will need to write your query like this:
ORDER BY X.Field
OFFSET 20 ROWS
FETCH NEXT 10 ROW ONLY OPTION (RECOMPILE)
And this will skip the first 20 records and fetch the next 10.

PHP PDO pagination foreach

I'm trying to create a pagination for my PDO query. I cant figure it out. I've tried numerous google searches, but nothing that will work for me. [I probably didn't search hard enough. I'm not sure]
This is my code:
$sql2 = "SELECT * FROM comments WHERE shown = '1'ORDER BY ID DESC";
$stm2 = $dbh->prepare($sql2);
$stm2->execute();
$nodes2= $stm2->fetchAll();
foreach ($nodes2 as $n1) {
echo "text";
}
I want to be able to limit 10 comments per page, and use $_GET['PAGE'] for the page.
Something that I tried
$sql2 = "SELECT * FROM comments WHERE shown = '1'ORDER BY ID DESC";
$stm2 = $dbh->prepare($sql2);
$stm2->execute();
$nodes2= $stm2->fetchAll();
$page_of_pagination = 1;
$chunked = array_chunk($nodes2->get_items(), 10);
foreach ($chunked[$page_of_pagination] as $n1) {
echo "text";
}
If someone could help out, I appreciate it.
You need to limit the query that you are performing, getting all values from the database and then limiting the result to what you want is a bad design choice because it's highly inefficient.
You need to do this:
$page = (int)$_GET['PAGE']; // to prevent injection attacks or other issues
$rowsPerPage = 10;
$startLimit = ($page - 1) * $rowsPerPage; // -1 because you need to start from 0
$sql2 = "SELECT * FROM comments WHERE shown = '1' ORDER BY ID DESC LIMIT {$startLimit}, {$rowsPerPage}";
What LIMIT does:
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants
More information here: http://dev.mysql.com/doc/refman/5.7/en/select.html
Then you can proceed getting the result and showing it.
Edit after comment:
To get all the pages for display you need to know how many pages are there so you need to do a count on that SELECT statement using the same filters, meaning:
SELECT COUNT(*) as count FROM comments WHERE shown = '1'
Store this count in a variable. To get the number of pages you divide the count by the number of rows per page you want to display and round up:
$totalNumberOfPages = ceil($count / $rowsPerPage);
and to display them:
foreach(range(1, $totalNumberOfPages) as $pageNumber) {
echo '' . $pageNumber . '';
}

Next and previous buttons

I know there are libraries etc that I could use to get this sorted but Im almost there with my code.
A little about the code and what it's trying to do. I have a mysql table where there are various news articles and grouped in categories of news.
I have managed to get a forward button working. So it looks for the next news article that is in the same category. This works and the code is below.
//Gets the next story from the same story type in line.
$query= "SELECT * FROM news WHERE storytype2 = '$storytype2' AND id > '$currentid'";
$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
$row = mysql_fetch_array($result);
$num_results = mysql_num_rows($result);
if ($num_results > 0){
echo "<td width=\"20%\"align=\"right\"><img title=\"Next News\" src=\"webImg/forwardarrow.png\"/></td></tr>";
}else{
echo "<td width=\"20%\"align=\"right\"></td></tr>";
}
//End of the next button
However, when I try do the same for the previous button. All I ever seem to get back is the first id of that category regardless of where my iteration is. For example, if I am on news article 10 and try to go to previous one which say has an id of 7 it will automatically show the first news article within that category, say id 4.
Below is the code.
//Gets the next story from the same story type in line.
$query= "SELECT * FROM news WHERE storytype2 = '$storytype2' AND id < '$currentid'";
$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
$row = mysql_fetch_array($result);
$num_results = mysql_num_rows($result);
if ($num_results > 0){
echo "<td width=\"20%\"align=\"left\"><img title=\"Previous News\" src=\"webImg/backarrow.png\"/></td>";
}else{
echo "<td width=\"20%\"align=\"left\"></td>";
}
//End of the next button
What have I done wrong?
Thanks
Neither of your queries is correct. Your "Next" code selects any row whose ID is higher than the current, not necessarily the next one; if you get the next one, it's just by accident.
You should use ORDER BY and LIMIT to control which row is selected:
Next:
SELECT *
FROM news
WHERE storytype2 = '$storytype2' AND id > '$currentid'
ORDER BY id
LIMIT 1
Previous:
SELECT *
FROM news
WHERE storytype2 = '$storytype2' AND id < '$currentid'
ORDER BY id DESC
LIMIT 1
Without any further information, I don't think you can assume that the first row of your queries will be the ID you're looking for. Ordering by ID first will probably solve your problem; you can also limit your query to one row, since it's the only one you're looking at. Something like the following would probably solve your problem (where x is $storytype2 and y is $currentid:
SELECT * FROM news
WHERE storytype2 = x
AND id < y
ORDER BY id DESC /* <-- THIS */
LIMIT 1
Use ORDER BY id ASC for the other case.
Note that the MySQL family of PHP is deprecated and support thereof will disappear, if it hasn't yet. Please look into PDO or MySQLi.
Note also that you are inserting a variable into SQL code directly, which is never a good idea. I hope you have some good input checks on your variables.
Let's look at the PDO way to get the previous article ID:
$dbh = new PDO(..);
// Use ? where dynamic input will come
$sql = $dbh->prepare('SELECT * FROM news
WHERE storytype2 = ?
AND id < ?
ORDER BY id DESC
LIMIT 1');
// Fill the ? safely with PDO's execute function
$sql->execute(array($storytype2, $currentid));
$result = $sql->fetch(PDO::FETCH_ASSOC);
if($result && isset($result['id'])) {
// Process previous ID
}

PHP add many rows to database

I have problem with database. I want to add about 10 new rows after pageload. It should check if there is an article with id (that is actually loading). If its not, add 10 of that id with different tag id.
$sprawdz = "SELECT id_artykulow FROM tag_art WHERE id_artykulow='".$_GET['id']."' " ;
$miasto = mysql_query($sprawdz);
$a = mysql_num_rows($miasto);
while ($a<=10){
$zm = "SELECT id FROM tag_content ORDER BY RAND() LIMIT 1";
$sw = mysql_query($zm);
while($row3=mysql_fetch_array($sw)){
$zmienna = "INSERT INTO tag_art(id_artykulow, id_tagow) VALUES ('".$_GET['id']."', '".$row3['id']."' ) ";
$cokolwiek = mysql_query($zmienna);
}
$a++;
}
There is two tables. One tag_content with id (of the tags), and another tag_art with id_artykulow (= id of the article) and id_tagow (id of the tag taken from tag_content)
Don't know why, but it doesn't add 10 rows (it should be for example ten id_artykulow = 10, with different id_tagow). How to fix it?
Thx for help and let me know if u need more informations (like more code etc.)
why do you have 2 while loops?
cant you just replace
while ($a<=10){
$zm = "SELECT id FROM tag_content ORDER BY RAND() LIMIT 1";
with
if ($a<=10){
$zm = "SELECT id FROM tag_content ORDER BY RAND() LIMIT " . (10-$a);
or just let the databse do all the work by:
$query = "INSERT INTO tag_art(id_artykulow, id_tagow) SELECT '".$_GET['id']."', id FROM tag_content ORDER BY RAND() LIMIT " . (10-$a);
(and i would also recomendate protection agains sql-injections, mysql_real_escape_string())
Or let the database do all the work:
// store id as mysql-variable, but let php force it to an integer first
mysql_query("SET #id = " . (int) $_GET['id']);
// calculate how many new art we need, to get 10, using greatest to avoid negative numbers
mysql_query("SELECT #art_needed := GREATEST(0, 10 - COUNT(*)) FROM tag_art WHERE id_artykulow = #id");
// Need to use prepere to be able to have an mysql-variable as limit
mysql_query("PREPARE art_stmt FROM 'INSERT INTO tag_art(id_artykulow, id_tagow) SELECT ?, id FROM tag_content ORDER BY RAND() LIMIT ?'");
// execute the query using the mysql-variables
mysql_query("EXECUTE art_stmt USING #id, #art_needed");
just reread my old answer, and no longer agrees with "or just let the databse do all the work by" for that answer, the database could do alot more.

How to build next and previous links with php?

I use this code to get the informations about a certain id
$sql = dbquery("SELECT * FROM `videos` WHERE `id` = ".$local_id." ");
while($row = mysql_fetch_array($sql)){
$video_id = $row["id"];
$video_title = $row["title"];
}
Let's say the link of a page would be example.com/video.php?id=34
How can i get the next and previous $video_id and $video_title depending on the current id?
A problem is that i can't increase or decrease the value of the current id by 1 because the 35 or 33 may be deleted in the meanwhile...
How can i achieve this?
//edit
I have a very big problem: the previous link sends me to the right link but the next link always sends me to the last video added in the database.
If i go to the last or first videos added in the database i get an error because there are no more next and previous videos added.
Perhaps two more queries would work ...
select id,title from videos where id < $local_id order by id desc limit 1
select id,title from videos where id > $local_id order by id asc limit 1
You have to use select and limit to get that one row you want, i.e.,
SELECT * FROM `videos` WHERE `id` < " . $local_id . " ORDER BY `id` DESC LIMIT 1
Or use > and ORDER BYidASC for the next video, instead of the previous I showed above.
Here you go through
// entry per page
$rowsPerPage = 3;
// Set page number
if(isset($_GET['page']))
$pageNum = $_GET['page'];
else
$pageNum = 1;
Note: Following code is use to show/set next & previous page number.
Note: If the current page is homepage then default $pageNum is 1 and
if $pageNum is set as 2, it will work as
if($pageNum){
$PreviousPageNumber = $pageNum - 1;
$NextPageNumber = $pageNum + 1;
echo '<a href="?page='. $PreviousPageNumber .'>Previous Page</a>';
echo '<a href="?page='. $NextPageNumber .'>Next Page</a>";
}
Note: Following code is use to show record affected by page numbers
$GetPreviousRecord = ($pageNum - 1) * $rowsPerPage;
Note: The first, optional value of LIMIT is the start position. Note:
And the second required value is the number of rows to retrieve.
$query = "SELECT * FROM post WHERE LIMIT $GetPreviousRecord, $rowsPerPage";
$result = mysql_query($query);
And in last use the WHILE loop to get all records from database by using LIMIT.

Categories