I am working on my PHP to fetch the data from mysql database to output them in the search results. I want to limit 50 rows in per page and if I have less than 50 rows like 21 rows in the page 2 then display the 21 rows.
I have got a problem with the limit, because when I tried to use LIMIT 0, 50, it will display total 71 rows which I only want to display no more than 50 in per page.
Here is what I have tried:
$search_mailbox = $link->prepare("SELECT * FROM $folder WHERE from_email LIKE ? OR subject LIKE ? OR message LIKE ? ORDER BY received_date DESC LIMIT 0, 50");
$search_mailbox->execute([$searchemail, $searchsubject, $searchmessage]);
And I have also tried this:
$search_mailbox = $link->prepare("SELECT * FROM $folder WHERE from_email LIKE ? OR subject LIKE ? OR message LIKE ? ORDER BY received_date DESC LIMIT $offset, $limit");
$search_mailbox->execute([$searchemail, $searchsubject, $searchmessage]);
It will not limit the rows I want. It will still show the 71 rows.
Here is the full code:
<?php
// Initialize the session
session_start();
//Connect to the database
require_once('config.php');
$searchemail = '%' . 'gmail.com' . '%';
$searchsubject = '%' . 'gmail.com' . '%';
$searchmessage = '%' . 'gmail.com' . '%';
$mailbox = $link->prepare("SHOW TABLES");
$mailbox->execute();
$folders = array();
$total = 0;
$total_rows = 0;
$i = 0;
while ($folder = $mailbox->fetch(PDO::FETCH_NUM)) {
$folder = $folder[0];
if (strpos($folder, 'users') !== false) {
$folder = str_replace('users', '', $folder);
}
else
{
$folders[$i] = $folder;
}
$i++;
}
foreach($folders as $folder) {
$search_mailbox = $link->prepare("SELECT * FROM $folder WHERE from_email LIKE ? OR subject LIKE ? OR message LIKE ? ORDER BY received_date DESC LIMIT 0, 50");
$search_mailbox->execute([$searchemail, $searchsubject, $searchmessage]);
if ($search_mailbox->rowCount() > 0) {
$total += $search_mailbox->rowCount();
}
}
$page = 1;
$limit = 50;
//$per_page = 50;
//$pages = ceil($total / $per_page);
$offset = ($page - 1) * $limit;
foreach($folders as $folder) {
$search_mailbox = $link->prepare("SELECT * FROM $folder WHERE from_email LIKE ? OR subject LIKE ? OR message LIKE ? ORDER BY received_date DESC LIMIT $offset, $limit);
$search_mailbox->execute([$searchemail, $searchsubject, $searchmessage]);
if ($search_mailbox->rowCount() > 0) {
foreach($search_mailbox->fetchAll() as $k => $row) {
$email_number = $row['id'];
$search_from = $row['from_email'];
$search_subject = $row['subject'];
$total_rows++;
echo $search_subject . '.........................' . $total_rows;
echo "<br>";
}
}
}
?>
I am unable to fetch the first 50 rows in the page 1 and I am also unable to fetch the 21 rows in the page 2.
What I am trying to achieve is when I am in page 1, I want to display the first 50 rows, then in the page 2 if I have another 50 rows then display the 50 rows, but if I have less than 50 rows like 21 rows then display the 21 rows.
Can you please show me an example how I can start with first 50 rows when I am in the page 1 then in page 2 display 21 rows to make in total 71 rows?
Thank you.
Related
I have the issue with LIMIT with foreach using PHP.
Basics: I have 50 different tables and in every table I have 2 rows.
When I try to add LIMIT 1 to $$modules_for_all, then I see 50 rows, but I want to see only 1. If I add LIMIT 2, then I see 100 rows.
How I can connect all these tables as a one LIMIT 1 to get 1 row in foreach?
<?php
for ($i = 1; $i <= 50; $i++) {
// $array_table_name contains names with tables
$table_names = $array_table_name[$i];
$modules_for_all = 'g_module_for_all_'.$i;
$$modules_for_all = $db->QueryFetchArrayAll("SELECT * FROM $table_names WHERE user='1' LIMIT 1");
}
for ($i = 1; $i <= 50; $i++) {
$modules_for_from = ${"g_module_for_all_$i"};
foreach ($modules_for_from as $m_foreach_as) {
echo $m_foreach_as['id'];
}
}
Example tables:
table_1
id date_added
1 2018-12-01 00:00:00
2 2018-12-02 00:00:00
table_2
id date_added
1 2018-12-03 00:00:00
2 2018-12-04 00:00:00
table_3
id date_added
1 2018-12-05 00:00:00
2 2018-12-06 00:00:00
Example foreach:
<?php
$array_table_name_1 = 'table_1';
$array_table_name_2 = 'table_2';
$array_table_name_3 = 'table_3';
$for_table_1 = $db->QueryFetchArrayAll("SELECT * FROM $array_table_name_1 WHERE id='1' LIMIT 1 ORDER BY date_added");
$for_table_2 = $db->QueryFetchArrayAll("SELECT * FROM $array_table_name_2 WHERE id='1' LIMIT 1 ORDER BY date_added");
$for_table_3 = $db->QueryFetchArrayAll("SELECT * FROM $array_table_name_3 WHERE id='1' LIMIT 1 ORDER BY date_added");
foreach ($for_table_1 as $m_foreach_as) {
echo $m_foreach_as['id'];
}
foreach ($for_table_2 as $m_foreach_as) {
echo $m_foreach_as['id'];
}
foreach ($for_table_3 as $m_foreach_as) {
echo $m_foreach_as['id'];
}
// Now result is '111' but I want only '1' (realted to make LIMIT 1 to all foreach)
The only way to connect the tables is by using a UNION. So you will need to build one large UNION query and then perform the select after the loop:
$tables = array();
for ($i = 1; $i <= 50; $i++) {
// $array_table_name contains names with tables
$table_names = $array_table_name[$i];
$tables[] = "(SELECT * FROM $table_names WHERE user='1')";
}
$query = implode(" UNION ", $tables) . " ORDER BY date_added LIMIT 1";
$result = $db->QueryFetchArrayAll($query);
foreach ($result as $row) {
echo $row;
}
You are gonna have to use UNION ALL for summing this rows together before ordering and limiting the results.
But keep in mind that a query like this will only work if all the tables in your array have the same structure. If they do not, then you will have to be specific in the query to make them have the same fields.
$array_table_name = [
'table_1',
'table_2',
'table_3',
];
$search_id = 1;
$selectsArray = [];
foreach ($array_table_name as $table_name) {
$selectsArray[] = "SELECT * FROM $table_name WHERE id='$search_id'\n";
}
As you see, I am using foreach() and not for() so you won't update the for by decreasing/increasing the number of tables in the array. So to finally have:
$selectsUnion = implode("UNION ALL\n", $selectsArray) . "ORDER BY date_added \nLIMIT 1";
You can see the code tested and query mounted here: https://3v4l.org/HXH2K
I solved my problem using this: foreach ($modules_for_from as $m_foreach_as) if ($tmp++ < 1) {
i wrote a query to get my posts with DESC order as you see its limitet to show 10 posts per page
but how i can find the post with "pid = 18" in what page?
TABLE:
pid, posterid, content
1 , 26 , blabla
2 , 8 , sec balnla
3 , 9 , lollll
4 , 26 , orddddd
5 , 10 , sssssdsd
...
PHP:
function getComments($poster){
$sql = "SELECT * FROM table WHERE posterid = $poster"
$smt = $db->query($sql);
$total = $smt->rowCount();
$result = $db->prepare($sql . " ORDER BY pid DESC $limit");
$result->execute();
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$Comments[] = $row;
}
return [
'comments' => $Comments,
'total' => $total
];
}
NEEDED FUNCTION:
$poster = 26;
$pid = 18;
$posttperpage = 10;
public function getPostPage($pid, $poster, $posttperpage)
{
$page = '';
$totlaPosts = getComments($poster)['total']; //70
$pages = $totlaPosts / $posttperpage; //7
for($i=0, $i<$totlaPosts, $i--)
{
// ?????
// i confuzed no idead what can i do :(
}
return $page; //it must be 2
}
Since pid is not necessarily consistent (you might have deleted some rows) you should have another query.
$stmt = $db->prepare("SELECT COUNT(1) FROM table WHERE pid <= ? AND poster = ?");
$stmt->execute([$pid, $poster]);
$count = $stmt->fetchColumn();
echo ceil($count / $posttperpage);
If you're looking to determine what page a post is on:
$k = 1;
for($i=0, $i<$pid; $i += $posttperpage){
$page = $k;
$k +=1;
}
//after loop $page now contains what page the post is on.
Is this what you're looking for?
In your LIMIT 0,10 you have a range of 10 items per page, right? If you want to keep track of which page you are viewing you need a variable that behaves like this:
$range = 10;
$currentPage = 2;
$offset = $range * ($currentPage - 1);
Inside your query you can change that 0 to $offset and there you have it, if you find your result in with this query it means your pid is in page 2, you can also increase the $currentPage by 1 if you can't find your result and so on.
This algo is simple,
You need to know the total of row, the position of your specific post and number of post per page.
And you do like this :
floor(position_of_you_post / number_total_of_post * number_of_post_per_page)
so if you have 100 post with 10 post per page and your post is the number 51, you can do :
51 /100 * 10 = 5.1
so the post is on the page 5
i am working with search function and pagination.
heres my code for search function
if( isset($_POST['searchBut']) ) {
$name = $_POST['inputSearch'];
$pageSearch = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
//lets say there are 10 items selected with this query
$searchQuery = "SELECT name,image,price,description FROM image WHERE name LIKE '%".$name."%' ";
$result = $db->query($searchQuery);
//getting total rows
$fetchTotalRow = mysqli_num_rows($result);
//getting total pages
$totalPages = ceil($fetchTotalRow / $perPage);
$links = "";
for ($i = 1; $i <= $totalPages; $i++) {
$links .= ($i != $pageSearch ) ? "<li><a href='collections.php?page=$i'>Page $i</span></a></li> " : "<li class='active'><a href='collections.php?page=$i'>Page $pageSearch</a></li> ";
}
}
now how do i limit my page to only 9 items in first page, and the last one will be on second page.
i've succesfully apply this to normal pagination with LIMIT($start,$offset) function, but this is for database, how to do this with resultset ?
You need to add LIMIT to your query.
//page 1
$searchQuery = "SELECT name,image,price,description FROM image WHERE name LIKE '%".$name."%' LIMIT 0, 9";
//page 2
$searchQuery = "SELECT name,image,price,description FROM image WHERE name LIKE '%".$name."%' LIMIT 1, 9";
MySQL will search the entire set first and then only return the specified LIMIT. LIMIT does not search only the first 9 posts...
Use LIMIT 0,9 or LIMIT 9 OFFSET 0
In your case,
$pageSearch = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
$pageOffset = $pageSearch - 1;
$limitQuery = "LIMIT $pageOffset , 9 ";
//lets say there are 10 items selected with this query
$searchQuery = "SELECT name,image,price,description FROM image WHERE name LIKE '%".$name."%' " . $limitQuery;
You have to use the LIMIT for that. You have to use LIMIT like LIMIT ".($pageSearch-1).", ".$perPage that's all.... Do as below:
$searchQuery = "SELECT name,image,price,description FROM image WHERE name LIKE '%".$name."%' LIMIT ".($pageSearch-1).", ".$perPage;
I followed one link here, and modified my code accordingly. What I am trying to do achieve is for example a table name media_ids contains 45 rows(which is dyanamic), I want to divide the no of rows in a group of 10 rows minimum (in my case four groups of 10 rows and 1 group of 5) and execute code of each group per hour.
For example from select record from id 1 to 10 then second hour from 11 to 20 and so on unless fetches the last record and start again from id 1.
I added a tracker, which check whats the current limit and proceed.But its giving me the required result what I am trying to achieve.
<?php
require('inc/dbConnect.php');
$lastPointerq = "select tracker from media_tracker";
$lastPointerResult = mysqli_query($con, $lastPointerq);
$lastPointerRes = mysqli_fetch_row($lastPointerResult);
$lastPointer = $lastPointerRes[0];
$lastPointer10=$lastPointer+10;
$currentMediaQuery = "select * from media_ids where id > ".$lastPointer." limit ".$lastPointer.",".$lastPointer10."";
$mediaQuery = mysqli_query($con, $currentMediaQuery);
if (mysqli_num_rows($mediaQuery) > 0) {
while ($row = mysqli_fetch_assoc($mediaQuery)) {
// do stuff…
echo $id=$row['id']."<br>";
}
}
else
{echo "0";}
if ($lastPointer + 10 > 40) {
$lastPointer = 1;
} else {
$lastPointer += 10;
}
mysqli_query($con, "update media_tracker set tracker = $lastPointer");
?>
I am assuming you are calling this script every hour via ajax/Js...
In your code if you delete some data from another script you may find your first row id i.e 100 !
require('inc/dbConnect.php');
$limit = 10 ;
$lastPointerq = "select tracker from media_tracker";
$lastPointerResult = mysqli_query($con, $lastPointerq);
$lastPointerRes = mysqli_fetch_row($lastPointerResult);
$lastPointer = $lastPointerRes[0];
$lastPointerRes = mysqli_fetch_assoc($lastPointerResult);
$lastPointer = empty($lastPointerRes['tracker']) ? 0 : $lastPointerRes['tracker'] ;
$lastPointer10=$lastPointer* $limit;
$currentMediaQuery = "select * from media_ids limit ".$limit." OFFSET ".$lastPointer10."";
$mediaQuery = mysqli_query($con, $currentMediaQuery);
if (mysqli_num_rows($mediaQuery) > 0) {
while ($row = mysqli_fetch_assoc($mediaQuery)) {
// do stuff…
echo $id=$row['id']."<br>";
}
}
else
{echo "0";}
//do a total row count query here and set as value of $total rather than 40
$total =40 ;
$flag = ceil($total/$limit);
if ($lastPointer == $flag) {
$lastPointer = 0;
} else {
$lastPointer ++;
}
mysqli_query($con, "update media_tracker set tracker = $lastPointer");
So like the title suggests, I am trying to retrieve records from multiple tables.
I have the following tables : ads1 , ads2 , ads3 ,.... each tables containes 1 or more records with auto_increment id and names of people under the column named names.
Let's say I have 10 records in each tables, and I have a pagination script that shows 5 records per page, that means 2 pages for each table, so I will have pages 1,2,3,4,5,6.
My algorithm doesn't do it correctly, on my first page it shows 5 record from the first table, 5 records from the second table , 5 records from the third table and so on... but I only want 5 records to be shown per page , not 5 from each table that I have, I want them to be shown correctly on pages 1 and 2 records from ads1 , on pages 3 and 4 records from ads2 and so on, hope you get the idea.
Can you please help me ?
here is my alogorithm :
for ($i=1;$i<=$kay;$i++)
{
$counter = 0;
$tablenow = 'ads'.$i;
$result = mysql_query("SELECT id FROM ".$tablenow." ");
$counter = $counter + mysql_num_rows($result);
$x=ceil($counter / $per_page);
$page = (isset ($_GET['page']) AND (int)$_GET['page'] > 0 AND (int)$_GET['page'] <= $x) ? (int)$_GET['page'] : 1;
$start = ($page - 1) * $per_page;
$sql = mysql_query("SELECT * FROM ".$tablenow." ORDER BY id DESC LIMIT
$start,$per_page ")or die(mysql_error());
while ($sqlg=mysql_fetch_assoc($sql))
{
// this is where I show the records.
}
}
PS: For only one table , the algorithm works exactly as it should, but when I have 2 or more tables it stops working correctly.
Here's one way to do it:
$count_tables = 10;
$query = '';
for ($table_no = 1; $table_no <= $count_tables; $table_no++ ) {
$query .= "SELECT * FROM ads" . $table_no . " UNION ";
}
// Remove trailing UNION
$query = preg_replace( '/ UNION \Z/', '', $query );
$result = mysql_query("SELECT id FROM ".$tablenow." ");
$total_rows = mysql_num_rows($result);
$max_page = ceil( $total_rows / $per_page );
// Fetch rows for the page
$query_for_page .= $query . " ORDER BY id DESC LIMIT $start, $per_page";
$page = ( isset ($_GET['page'])
AND (int)$_GET['page'] > 0
AND (int)$_GET['page'] <= $max_page ) ? (int)$_GET['page'] : 1;
$start = ($page - 1) * $per_page;
$page_results = mysql_query( $query_for_page ) or die( mysql_error() );
while ( $row = mysql_fetch_assoc( $page_results ) ) {
// this is where I show the records.
}
Hope this helps.
You have to execute only one query, which will be an UNION of the results of all desired tables. If you execute SELECTs in each table individually, you cannot track the total results in an accurate way.