Hi everyone I've been extracting rows from a SQL table 1 by 1. I wrote this code two years ago and realise how hideously ineffective it is. I'd like to speed things up by typing up a simple for-loop to automate the coding.
$maxRows_dd1 = 10;
$pageNum_dd1 = 0;
if (isset($_GET['pageNum_dd1'])) {
$pageNum_dd1 = $_GET['pageNum_dd1'];
}
$startRow_dd1 = $pageNum_dd1 * $maxRows_dd1;
$maxRows_dd2 = 10;
$pageNum_dd2 = 1;
if (isset($_GET['pageNum_dd2'])) {
$pageNum_dd2 = $_GET['pageNum_dd2'];
}
$startRow_dd2 = $pageNum_dd2 * $maxRows_dd2;
$maxRows_dd3 = 10;
$pageNum_dd3 = 2;
if (isset($_GET['pageNum_dd3'])) {
$pageNum_dd3 = $_GET['pageNum_dd3'];
}
$startRow_dd3 = $pageNum_dd3 * $maxRows_dd3;
... dd4 to dd99 go in between!
$maxRows_dd100 = 10;
$pageNum_dd100 = 99;
if (isset($_GET['pageNum_dd99'])) {
$pageNum_dd32 = $_GET['pageNum_dd99'];
}
$startRow_dd99 = $pageNum_dd99 * $maxRows_dd99;
which corresponds to:
mysql_select_db($database_rent, $rent);
$query_dd1 = "SELECT * FROM rent";
$query_limit_dd1 = sprintf("%s LIMIT %d, %d", $query_dd1, $startRow_dd1, $maxRows_dd1);
$dd1 = mysql_query($query_limit_dd1, $rent) or die(mysql_error());
$row_dd1 = mysql_fetch_assoc($dd1);
if (isset($_GET['totalRows_dd1'])) {
$totalRows_dd1 = $_GET['totalRows_dd1'];
} else {
$all_dd1 = mysql_query($query_dd1);
$totalRows_dd1 = mysql_num_rows($all_dd1);
}
$totalPages_dd1 = ceil($totalRows_dd1/$maxRows_dd1)-1;
mysql_select_db($database_rent, $rent);
$query_dd2 = "SELECT * FROM rent";
$query_limit_dd2 = sprintf("%s LIMIT %d, %d", $query_dd2, $startRow_dd2, $maxRows_dd2);
$dd2 = mysql_query($query_limit_dd2, $rent) or die(mysql_error());
$row_dd2 = mysql_fetch_assoc($dd2);
if (isset($_GET['totalRows_dd2'])) {
$totalRows_dd2 = $_GET['totalRows_dd2'];
} else {
$all_dd2 = mysql_query($query_dd2);
$totalRows_dd2 = mysql_num_rows($all_dd2);
}
$totalPages_dd2 = ceil($totalRows_dd2/$maxRows_dd2)-1;
mysql_select_db($database_rent, $rent);
$query_dd3 = "SELECT * FROM rent";
$query_limit_dd3 = sprintf("%s LIMIT %d, %d", $query_dd3, $startRow_dd3, $maxRows_dd3);
$dd3 = mysql_query($query_limit_dd3, $rent) or die(mysql_error());
$row_dd3 = mysql_fetch_assoc($dd3);
if (isset($_GET['totalRows_dd3'])) {
$totalRows_dd3 = $_GET['totalRows_dd3'];
} else {
$all_dd3 = mysql_query($query_dd3);
$totalRows_dd3 = mysql_num_rows($all_dd3);
}
$totalPages_dd3 = ceil($totalRows_dd3/$maxRows_dd3)-1;
... all the way to dd100!!!
How would I use a for loop to speed typing up all this code for each block of code from dd1 to dd100?
Read about arrays and for() loops.
This is a much more efficient code to do exactly what you do above:
<?php
// You only need to do these once as they are the same throughout
mysql_select_db($database_rent, $rent);
$maxRows = 10;
// This code gets the total number of rows in the database
$totalRowsAll = mysql_fetch_assoc(mysql_query("SELECT count(*) AS total FROM rent", $rent));
$totalRowsAll = (int) $totalRowsAll['total'];
?>
<div class="tab_container">
<div id="tab1" class="tab_content">
<table width="100%" border="0" cellspacing="5" cellpadding="5" id="1">
<?php
for ($i = 0; $i < 100; $i++) {
// Calcluate value for this iteration and query database
$pageNum = (isset($_GET['pageNum_dd'.($i + 1)])) ? (int) $_GET['pageNum_dd'.($i + 1)] : $i;
$startRow = $pageNum * $maxRows;
$query = "SELECT * FROM rent LIMIT $startRow, $maxRows";
$result = mysql_query($query, $rent) or die(mysql_error($rent));
$totalRows = (isset($_GET['totalRows_dd1'])) ? (int) $_GET['totalRows_dd1'] : $totalRowsAll;
${'totalPages_dd'.($i + 1)} = ceil($totalRows / $maxRows) - 1;
// Now print this row
?>
<tr height="100px" align="center">
<?php
while ($row = mysql_fetch_assoc($query)) {
?>
<td style="background-color: <?php echo $row['colour']; ?>;" onclick="window.location='pay.php?id=<?php echo $row['dNo']; ?>&user=<?php echo $username; ?>'" onmouseover="this.style.cursor='pointer'">
<form action="pay.php?id=<?php echo $row['dNo']; ?>&user=<?php echo $username; ?>" method="post">
<input type="hidden" id="<?php echo $row['dNo']; ?>">
<input type="hidden" value="<?php echo $username; ?>">
<button type="submit" class="link" id="t<?php echo $row['dNo']; ?>">
<span><?php echo $row['dNo']; ?></span>
</button>
</form>
</td>
<?php
} // End while
?>
</tr>
<?php
} // End for
?>
</table>
</div>
</div>
...however:
I'm fairly sure this could be summed up in a single query to get all the results you need, which would be much more efficient and drastically reduce database load. But because of the $_GET['pageNum_dd*'] and $_GET['totalPages_dd*'] variables which are used on a per row basis, I am not 100% sure about this, and I can't work out how this would be done without knowing more about what is produced. You need to examine whether or not these parameters that can be passed are actually necessary/useful. As it is, they may be cause rows of a varying length, with an unequal number of cells per row - which is probably not what you want.
The same also goes for the variables $totalPages_dd*, which are assigned below but never used anywhere. They may not be useful, and assigning them may be pointless.
Related
I have category table which include 35 category inside. I want them aline into four div with one while loop.
<?php
$count = 0;
$cat = pullcategories();
$catcount = mysqli_num_rows($cat);
$percat = ceil($catcount / 4);
$topcats = pulltopcategories($count, $percat);
//same with pullcategories, just LIMIT $count,$per //
while ($topcats = mysqli_fetch_object($topcats)) {
?>
<div class="col3">
<ul class="list-unstyled list-dashed">
<li>
$topcats->title
</li>
</ul>
</div>
<?php
$count = $count + $percat;
$percat = $percat * 2;
}
?>
$count = 0;
$cat = pullcategories();
$catcount = mysqli_num_rows($cat);
$percat = ceil($catcount / 4);
$topcats = pulltopcategories($count, $percat);
This breaks your lists down in to 4 parts, and you would need to call "$topcats = pulltopcategories($count, $percat);" 4 times to be able to get through all the data.
I would change it to be something like this.
Assuming that "pulltopcategories($count, $percat)" uses count as the limit, and percat as the offset in the SQL this should work.
Please try and let me know - I can fix any mistakes if there are any (my PHP is a little rusty and i dont have data to try this with)
<?php
$count = 0;
$cat = pullcategories();
$catcount = mysqli_num_rows($cat);
$percat = ceil($catcount / 4);
while ($count < catcount){ /* Loop until you have finished all cats */
$topcats = pulltopcategories($count, $percat);
echo "<div class="col3">
<ul class='list-unstyled list-dashed'>";
while ($topcats = mysqli_fetch_object($topcats)) {
echo "<li>
<a href=''>$topcats->title</a>
</li>"
}
echo "</ul>
</div>";
$count = $count + $percat;
}
?>
Ok so the problem I'm having is very strange. I have a blog website that displays a list of posts, and i made a system to select only 10 posts at a time. and yet on the second generated page 12 results are shown (the last 2 are duplicates)
//removed url because problem solved and i dont want to get sql injected
if you goto my project above and look at the second page of posts 12 entry's are shown with the last 2 being duplicates of the 3rd(and last) page...what is going on?! they should not be able to appear because the sql LIMIT function should restrict the displayed posts to 10.
here is the code for mainpage .php
<?php
session_start();
ob_start();
if ($_SERVER["REQUEST_METHOD"] == "POST"){//this works in my tests.
$low = 0;
$high = 10; //this loop/if method works in conjunction with the code at the bottom of this page
$e = 1;//starts at 1 because 1 itself is defined my default at the bottom of the page
while($_SESSION['i'] != $e){
$e++;
if (isset($_REQUEST["p$e"])){
$u = 1;
while($u != $e){
$u++;
$low = $low + 10;
$high = $high +10;
}
}
}}else{
$low = 0;
$high = 10;
}
?>
<!doctype html>
<!-- AUTHOR:JOSH FAIRBANKS -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Home Page</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<nav>
<ul>
<li><div id = "new">Create new post</div></li>
<li><div id = "veiw">Veiw posts</div></li>
</ul>
</nav>
<main>
<?php
$link = mysqli_connect( 'localhost', 'username', 'password' );
mysqli_select_db( $link, 'mydatabasename' );
$results = mysqli_query( $link, "SELECT LEFT(post, 575) as post FROM Users where verified = 1 ORDER BY `id` DESC LIMIT $low , $high" ); //this displayes all the posts that have been verified
while( $record = mysqli_fetch_assoc( $results ) ) {
$post = $record['post'];
$count = mysqli_affected_rows( $link );
//ORDER BY YEAR(Date) DESC, MONTH(Date) DESC, DAY(DATE) DESC
$post .= "</td></tr></table>";
print $post;
}
$vresults = mysqli_query( $link, "SELECT post FROM Users where verified = 1" );
while( $vrecord = mysqli_fetch_assoc( $vresults ) ) {
$vpost = $vrecord['post'];
$vcount = mysqli_affected_rows( $link );
$_SESSION['vcount'] = $vcount;
//
//these mirror variables arent seen and just are used to count the total amount of posts
//not just the ones on the page
}
mysqli_free_result( $results );
mysqli_close( $link );
?>
<form method = "post" action = "mainPage.php">
<table>
<tr><td>Page Number: </td><!--<td><input type = "submit" name = "p1" value = "1"></td>-->
<?php
$i = 0;
print "displaying low: $low high: $high";
for($j = 0; $j < $vcount; $j++) //modulus
{
if($j % 10 == 0)
{
$i++;
$_SESSION['i'] = $i;
print "<td><input type = 'submit' name ='"."p".$i. "' value = '$i'></td>";
}
}
?>
</tr>
</table>
</form>
</main>
</body>
</html>
I know this code is a bit of a mess :p but i swear it works except for this frustrating issue. any and all help appreciated.
I guess your problem at $high variable... Records per page always constant. But seems that you are increment in one place.
if ($_SERVER["REQUEST_METHOD"] == "POST"){//this works in my tests.
$low = 0;
$high = 10; //this loop/if method works in conjunction with the code at the bottom of this page
$e = 1;//starts at 1 because 1 itself is defined my default at the bottom of the page
while($_SESSION['i'] != $e){
$e++;
if (isset($_REQUEST["p$e"])){
$u = 1;
while($u != $e){
$u++;
$low = $low + 10;
$high = 10;
}
}
}}else{
$low = 0;
$high = 10;
}
?>
I have a php code similar to below. I want to make just last row bold. Is it possible?
<table border = "5">
<?php
if (isset($startdate) && isset($enddate) ){
$query = "storedprocedure '$startdate','$enddate','field1'";
$result = mssql_query($query);
while ($rows = mssql_fetch_array($result) ) {
echo "<tr><td>".$rows[0]." <td>".$rows[1]."
<td>".$rows[2]." <td>".$rows[3]."
<td>".$rows[4]." <td>".$rows[5]." ";
}
}
</table>
You can use mssql_num_rows() to get the total number of rows returned by the query before you loop through them, and then (with the use of a counter), see if the current row is the last one and then apply any styling you want:
<table border = "5">
<?php
if (isset($startdate) && isset($enddate) ){
$query = "storedprocedure '$startdate','$enddate','field1'";
$result = mssql_query($query);
$numRows = mssql_num_rows($result);
if ($numRows > 0) {
$counter = 0;
while ($rows = mssql_fetch_array($result) ) {
$style = ($counter++ == ($numRows - 1)) ? ' style="font-weight: bold;"' : '';
?>
<tr>
<td<?=$style;?>><?=$rows[0];?></td>
<td<?=$style;?>><?=$rows[1];?></td>
<td<?=$style;?>><?=$rows[2];?></td>
<td<?=$style;?>><?=$rows[3];?></td>
<td<?=$style;?>><?=$rows[4];?></td>
</tr>
<?
}
}
}
?>
</table>
I find that copying the data to an array (or better yet object) is much better, then outputting the data at the end makes these sorts of things easier.
in this case, if you drop the data into an array, you can then use lovely things like count() to see how many rows there are etc. This lets you do a simple check in the display loop to see if it is the last element in the array.
This should work:
<?php
if (isset($startdate) && isset($enddate))
{
$res=array();
$query = "storedprocedure '$startdate','$enddate','field1'";
$result = mssql_query($query);
while ($rows = mssql_fetch_array($result) )
{
$res[]=$rows;
}
}
?>
<table border = "5" id="1">
<?php
$numberRows=count(%res);
for($i=0;$i<$numberRows;$i++)
{
$boldStart="";
$boldEnd="";
if($i==($numberRows-1))
{
$boldStart="<B>";
$boldEnd="</B>";
}
echo "<tr><td>".$boldStart.$rows[$i][0].$boldEnd." </td><td>".$boldStart.$rows[$i][1].$boldEnd."
</td><td>".$boldStart.$rows[$i][2].$boldEnd." </td><td>".$boldStart.$rows[$i][3].$boldEnd."
</td><td>".$boldStart.$rows[$i][4].$boldEnd." </td><td>".$boldStart.$rows[$i][5].$boldEnd." </td>";
}
?>
</table>
Just use CSS:
t1 tr:last-child{font-weight:bold;}
I am trying to setup paging on my site using Ajax, I've inherited a script and put it into practice at the following link - http://www.testing.arrivaldesign.co.uk/properties.
I've got it working to an extent, but it's set to show the first 9 records and then carry on from there, but it's only showing the first 9 on the first page, but then when you click to the next page it just repeats 4 of the existing records.
As far as I can see it's to do with limit on my query, but I don't know how to get it working?
This is the code for the ajax side of things.
<?php
include('Connections/connection.php');
include 'functions.php';
// Pagination params
$basePath = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
$qString = $_REQUEST['qString'];
$items = $_REQUEST['items'];
$loadPage = $_REQUEST['p'];
$current = $_REQUEST['current'];
$limit = $loadPage*$items;
$min = ($max-$items)+1;
mysql_select_db($database, $conn);
$query_RSproperty = "SELECT properties.*, type.* FROM (properties LEFT JOIN type ON properties.propType=type.typeID) WHERE offline = 'N' ORDER BY propID ASC LIMIT 0, $limit";
$RSproperty = mysql_query($query_RSproperty, $conn) or die(mysql_error());
$row_RSproperty = mysql_fetch_assoc($RSproperty);
$totalRows_RSproperty = mysql_num_rows($RSproperty);
$maxItems = $totalRows_RSproperty;
// New pagination
$pagination = paginator($basePath . $qString, $loadPage, $maxItems, $items);
// Direction is important for the script to determine which way to animate, left or right.
$direction = 'left';
if ($current < $loadPage) {
$direction = 'right';
}
$paginatedStyle = 'style="left:'.($direction == 'left' ? '0' : '-960px').';"';
// The paginated content HTML slide
$page = '<div class="paginated" id="" '.$paginatedStyle.'>';
ob_start();
do {
?>
<div class="grid-1third res-block">
<div class="prop-brief-desc">
<div class="grid-140"><img src="/prop-images/thumbs/<?php echo $row_RSproperty['propImage1']; ?>" width="140" height="105" alt=""></div>
<div class="grid-140 fr">
<h2><?php echo $row_RSproperty['propBeds']; ?> Bed <?php echo $row_RSproperty['typeName']; ?></h2>
<?php
$fulladdress = $row_RSproperty['propAddress1'] . '<br />' . $row_RSproperty['propCity'] . ', ' . $row_RSproperty['propCounty'] . '<br />' . $row_RSproperty['propPostcode'];
?>
<p><?php echo $fulladdress; ?></p>
</div>
</div>
<div class="prop-brief-options<?php echo $no == 2 || $no == 3 ? " hide" : ""; ?>" id="newopt<?php echo $no; ?>">
<div class="grid-140"> Details Arrange Viewing Place Bid Buy it Now </div>
<div class="grid-140 fr">
<dl>
<dt>Auction Ending:</dt>
<dd><?php
if(!function_exists('countdown')) {
function countdown($year, $month, $day, $hour, $minute) {
$the_countdown_date = mktime($hour, $minute, 0, $month, $day, $year, -1);
$current = time();
$difference = $the_countdown_date - $current;
if ($difference < 0) $difference = 0;
$days = floor($difference/60/60/24);
$hours = floor(($difference - $days*60*60*24)/60/60);
$minutes = floor(($difference - $days*60*60*24 - $hours*60*60)/60);
echo $days."d ".$hours."h ".$minutes."m";
}
}
$theyear = date("Y",strtotime($row_RSproperty['propEndDate']));
$themonth = date("n",strtotime($row_RSproperty['propEndDate']));
$theday = date("d",strtotime($row_RSproperty['propEndDate']));
$thehour = date("H",strtotime($row_RSproperty['propEndDate']));
$theminute = date("i",strtotime($row_RSproperty['propEndDate']));
countdown($theyear,$themonth,$theday,$thehour,$theminute);
?></dd>
<?php if ($row_RSproperty['propCurrBid'] > 0) { ?>
<dt>Current bid:</dt>
<dd>£<?php echo number_format($row_RSproperty['propCurrBid']); ?></dd>
<?php } else { ?>
<dt>Starting Price:</dt>
<dd>£<?php echo number_format($row_RSproperty['propStartPrice']); ?></dd>
<?php } ?>
<dt>Buy it now:</dt>
<dd><span class="green">£<?php echo number_format($row_RSproperty['propBinPrice']); ?></span></dd>
</dl>
</div>
</div>
</div>
<?php
} while ($row_RSproperty = mysql_fetch_array($RSproperty));
/*while ($min <= $max) {
$page .= '<li>'.$min.'</li>';
$min++;
}*/
$page .= ob_get_contents();
ob_end_clean();
$page .= '</div>';
// return the JSON
echo json_encode(array( 'pagination' => $pagination, 'page' => $page, 'current' => $loadPage ));
exit;
?>
Many thanks
Chris
That's because you have hard coded LIMIT as 0 in your query
$query_RSproperty = "SELECT properties.*, type.* FROM (properties LEFT JOIN type ON properties.propType=type.typeID) WHERE offline = 'N' ORDER BY propID ASC LIMIT 0, $limit";
So when you move on second page, the query must be getting generated like follow
$query_RSproperty = "SELECT properties.*, type.* FROM (properties LEFT JOIN type ON properties.propType=type.typeID) WHERE offline = 'N' ORDER BY propID ASC LIMIT 0, 4";
hence you re getting first 4 records. If you want to retrieve the next set of records on subsequent pages, then you have to make 0 in LIMIT 0, $limit dynamic like:
$query_RSproperty = "SELECT properties.*, type.* FROM (properties LEFT JOIN type ON properties.propType=type.typeID) WHERE offline = 'N' ORDER BY propID ASC LIMIT $offset, $limit";
You have to calculate $offset depending on how much results you are displaying per page. On first page, offset will always be 0. If you are displaying 10 records per page, then on second page, offset will be 11, on third offset will be 21 and so on.
My main issue is the number of times I query the database (see below). Also, I would like to check that the current product (optionsToProducts.productID) has options for the current optionName before outputting the select statement! See the final image below to see the blank select box...
I have 8 tables in total, but the 3 that matter are:
optionNames
http://www.grabb.co.uk/stack/001.png
productOptions
http://www.grabb.co.uk/stack/002.png
optionsToProducts
http://www.grabb.co.uk/stack/003.png
<?php
$i=0;
$optionsquery = "SELECT * FROM optionNames WHERE categoryID = ".$categoryID."";
$optionsresult= mysql_query($optionsquery) or die(mysql_error());
while ($optionnames = mysql_fetch_array($optionsresult)) {
$i++;
$optionname = $optionnames["optionName"];
$optionID = $optionnames["optionNamesID"];
//echo $optionname."<br />";
?>
<label for="option<?php echo $i; ?>"><?php echo $optionname; ?></label>
<select name="option<?php echo $i; ?>" id="<?php echo $i; ?>">
<?php
//$optionvalues = "SELECT * FROM (optionsToProducts,productOptions) WHERE optionsToProducts.productID = ".$productID." AND productOptions.optionNamesID = ".$optionID."";
//echo $optionvalues."<br /><br />";
$optionvalues = "SELECT * FROM optionsToProducts WHERE productID = ".$productID."";
$valuesresult= mysql_query($optionvalues) or die(mysql_error());
while ($optionvals = mysql_fetch_array($valuesresult)) {
$valueName = $optionvals["optionValue"];
$valueID = $optionvals["productOptionsID"];
//echo $valueName."<br />";
$optionfinal = "SELECT * FROM productOptions WHERE productOptionsID = ".$valueID." AND optionNamesID = ".$optionID."";
$finalresult= mysql_query($optionfinal) or die(mysql_error());
while ($optionlast = mysql_fetch_array($finalresult)) {
$optionValueName = $optionlast["optionValue"];
$optionValueID = $optionlast["productOptionsID"];
$num_rows = mysql_num_rows($finalresult);
?>
<option value="<?php echo $optionValueID; ?>"><?php echo $optionValueName; ?></option>
<?php
}
}
echo "</select>";
}
?>
final Output:
http://www.grabb.co.uk/stack/004.png
As always, your help is appreciated. Thank you.
Since you tagged this question with the join tag, you probably know you need to write a join query to get what you need.
<?php
$i=0;
$query = "SELECT options.optionName, options.optionNamesID, po.optionValue, po.productOptionsID
FROM optionNames AS options
INNER JOIN productOptions AS po ON po.optionNamesID=options.optionNamesID
INNER JOIN optionsToProducts AS otp ON otp.productOptionsID=po.productOptionsID
WHERE otp.productID=" . (int) $productID
. " AND options.categoryID=" . (int) $categoryID;
$result = mysql_query($query);
if($result) {
$rows = array();
while($row = mysql_fetch_assoc($result) ) {
$rows[] = $row;
}
$i = 0;
$optionId = null;
foreach($rows as $row) {
if($optionId != $row['optionNamesID']) {
$optionId = $row['optionNamesID'];
?>
<label for="option<?php echo $optionId; ?>"><?php echo $row['optionName']; ?></label>
<select name="option<?php echo $optionId; ?>" id="<?php echo $optionId; ?>">
<?php } ?>
<option value="<?php echo $row['productOptionsID']; ?>"><?php echo $row['optionValue']; ?></option>
<?php
//Close select element when the optionNamesID changes or on the last row
if( (isset($rows[$i + 1]) && $rows[$i + 1]['optionNamesID'] != $optionId) ||
!isset($rows[$i + 1]) ) { ?>
</select>
<?php }
$i++;
}
} else {
//Debug query, remove in production
echo mysql_error();
}
?>
I also made some small changes - I use the optionNamesID in the select and label tag names - I don't know how you knew previously which select belonged to which option.
I also assumed that categoryID and productID came from somewhere, since it's not specified in the code.
Pushing all the rows to an array at the beginning is optional, but it makes the code a bit more organized (since you can check ahead in the array to see where to close the select tags).
NOTICE - this code is untested so there could some minor typos. Please make the needed corrections if necessary.