This is part of code from my backoffice page. ( is an edit.php page for a user to edit / modify )
// first query to get cats from user table
$query = "select * from user where name='".$_SESSION['username']."' order by id ASC limit 1";
$result=mysql_query($query);
if (mysql_num_rows($result)) {
while($row=mysql_fetch_array($result)){
$cat1 = $row['cat1'];
$cat2 = $row['cat2'];
$cat3 = $row['cat3'];
$cat4 = $row['cat4'];
$cat5 = $row['cat5'];
$cat6 = $row['cat6'];
$cat7 = $row['cat7'];
$cat8 = $row['cat8'];
$cat9 = $row['cat9'];
$cat10 = $row['cat10'];
}
}
// now i want to build 10 select boxes with selected according the user table $cats
// below is what i can build to first box $cat1
// is there a way i can produce this for the 10 select boxes whitout having to make 10 cycles of bellow code
<select name="theme" id="theme">
<?php
$q1 = 'SELECT * FROM cats ORDER BY title ASC';
$r1 = mysql_query($q1);
while( $row = mysql_fetch_array($r1)) {
if ( $cat1 == $row['id'] ) {
print "<option class=\"cssoption\" selected=\"selected\" value=\"".$row['id']."\">".htmlentities($row['title'])."</option>";
}
else {
print "<option class=\"cssoption\" value=\"".$row['id']."\">".htmlentities($row['title'])."</option>";
}
}
?>
</select>
I am not a coder so this might not be effective code.
Hope someone can help me here and understands what i am trying to do.
Many Thanks.
The code is fine. This 10 cycles as you name it is a almost zero cost.
This is the usual way we do it, we fetch sequentialy the records one by one.
In addition it makes no sense to ask not to do the 10 cycles because you are applying an if else condition in the same time, this means that you check every record if the cat id is the same with the row so you need the loop.
On the other hand if for some reason you want to skip some records, you can use the mysql seek function to start fetching from the desired record.
for($i=0;$i<99999;$i++)
(9999*9999);
echo 'This time the cost of this loop was:',(microtime()-$start),' seconds.';
?>
Related
I didn't know exactly how to word this question but by do something I mean that I would like to hide or not show my "next" button that is shown below. I have a script that pulls all the images from MySQL and prints them to my page by 30 images per page and the next 30 will create a new page that is activated by my back/next buttons. My "back" button has a if statement if $startrow isn't >= 0 than it won't show but I would like the same concept with my next button when the last row in my database is shown and it hides my next button.
I was thinking if you can detect the first empty row or the last row of the database and if so hide the next button. Otherwise it keeps adding 30 to $startrow when nothing is shown on screen.
I found a script helping me with this here but it didn't tell me how to hide the next button.
<?php
$startrow = $_GET['startrow'];
if (!isset($_GET['startrow']) or !is_numeric($_GET['startrow'])) {
$startrow = 0;
} else {
$startrow = (int)$_GET['startrow'];
}
?>
<?php
$db = mysqli_connect("localhost", "root", "", "media");
$uploaded = mysqli_query($db, "SELECT * FROM images LIMIT $startrow, 30");
while ($row = mysqli_fetch_array($uploaded)) {
echo "<div class='img_container'>";
echo "<li><img class='img_box' src='uploads/images/".$row['image_title']."' ></li>";
echo "</div>";
}
$prev = $startrow - 30;
if ($prev >= 0) {
echo '<div class="prevRow">Back</div>';
}
echo '<div class="nextRow">Next</div>';
?>
You could try something like
$num_rows = 30; // rows on a page
$db = mysqli_connect("localhost", "root", "", "media");
// get total possible rows
$res = mysqli_query($db, "SELECT count(id) FROM images");
$row = $res->fetch_row();
$total_rows = $row[0];
$res->close();
$uploaded = mysqli_query($db, "SELECT * FROM images LIMIT $startrow, $num_rows");
while ($row = mysqli_fetch_array($uploaded)) {
. . .
}
$prev = $startrow - $num_rows;
if ($prev >= 0) {
echo '<div class="prevRow">Back</div>';
}
if ( $startrow+$num_rows < $total_rows ) {
echo '<div class="nextRow">Next</div>';
}
Potentially a little faster than the answer from #RiggsFolly, you can modify your existing query to count the rows.
SELECT SQL_CALC_FOUND ROWS * FROM images LIMIT $startrow, 30
Then, after the query returns, you run a second query to get the answer:
SELECT FOUND_ROWS()
The FOUND_ROWS() function returns the number of rows the previous query would have returned, without LIMIT (or an offset).
This is probably not as fast as your original query would be in isolation, but should be slightly faster than SELECT COUNT(...) ... followed by your original query. With small data sets, though, any differences will likely be below measurable limits.
See also https://dev.mysql.com/doc/refman/5.7/en/information-functions.html
You can also combine these things into a stored procedure that accepts items per page and page number, and returns all of the records along with metadata items such as the total number of pages.
Can't believe this is giving me a problem but here it is. An example of the query and code is:
$sql = "SELECT
o.order_id, o.order_number, o.broker_id, o.agent_id
FROM orders o";
$sql_res = safe_query($sql);
/* I want to echo broker_id and angent_id only once here,
before the while loop, because the values are all the same */
while ($row = pg_fetch_array($sql_res)){
echo $order_number;
}
Assume broker and agent id numbers are each the same in every row. I don't want to echo them every time in the loop. I just want them to echo one time before the loop. Since they are the same, it does not matter which row they are echoed from.
I figured out a different way for a means to an end. It works well.
$sql = "SELECT
o.order_id, o.order_number, o.broker_id, o.agent_id
FROM orders o";
$sql_res = safe_query($sql);
$count = 0;
while ($row = pg_fetch_array($sql_res)){
if ($count == 0) {
echo $broker_id;
echo $agent_id;
}
echo $order_number;
$count += 1;
}
I realize I'm echoing the broker and agent IDs inside the while loop, but it's only an echo the first time through, and I can display them at top. And then every unique order is echoed. Visually, it accomplished what was needed for the end user.
I have a query like this:
$sql = "SELECT * FROM doctors WHERE city ='$city' LIMIT 10 ";
$result = $db->query($sql);
And I show the result like this :
while($row = $result->fetch_object()){
echo $row->city;
}
The Problem :
Mysql , will search through my database to find 10 rows which their city field is similar to $city.
so far it is OK;
But I want to know what is the exact row_number of the last result , which mysql selected and I echoed it ?
( I mean , consider with that query , Mysql selected 10 rows in my database
where row number are:
FIRST = 1
Second = 5
Third = 6
Forth = 7
Fifth = 40
Sixth = 41
Seventh = 42
Eitghth = 100
Ninth = 110
AND **last one = 111**
OK?
I want to know where is place of this "last one"????
)
MySQL databases do not have "row numbers". Rows in the database do not have an inherent order and thereby no "row number". If you select 10 rows from the database, then the last row's "number" is 10. If each row has a field with a primary id, then use that field as its "absolute row number".
You could let the loop run and track values. When the loop ends, you will have the last value. Like so:
while($row = $result->fetch_object()){
echo $row->city;
$last_city = $row->city;
}
/* use $last_city; */
To get the row number in the Original Table of the last resultant (here, tenth) row, you could save the data from the tenth row and then, do the following:
1. Read whole table
2. Loop through the records, checking them against the saved data
3. Break loop as soon as data found.
Like So:
while($row = $result->fetch_object()){
echo $row->city;
$last_row = $row;
}
Now, rerun the query without filters:
$sql = "SELECT * FROM doctors";
$result = $db->query($sql);
$rowNumber = 0;
while($row = $result->fetch_object()) {
if($row == $last_row) break;
$rowNumber++;
}
/* use $rowNumber */
Hope this helps.
What you can do is $last = $row->id; (or whatever field you want) inside your while loop - it will keep getting reassigned with the end result being that it contains the value of the last row.
You could do something like this:
$rowIndex = 0;
$rowCount = mysqli_num_rows($result);
You'd be starting a counter at zero and detecting the total number of records retrieved.
Then, as you step through the records, you could increment your counter.
while ( $row = $result->fetch_object() ) {
$rowIndex++;
[other code]
}
Inside the While Loop, you could check to see whether the rowIndex is equal to the rowCount, as in...
if ($rowIndex == $rowCount) {
[your code]
}
I know this is a year+ late, but I completely why Andy was asking his question. I frequently need to know this information. For instance, let's say you're using PHP to echo results in a nice HTML format. Obviously, you wouldn't need to know the record result index in the case of simply starting and ending a div, because you could start the div before the loop, and close it at the end. However, knowing where you are in the result set might affect some styling decisions (e.g., adding particular classes to the first and/or last rows).
I had one case in which I used a GROUP BY query and inserted each set of records into its own tabbed card. A user could click the tabs to display each set. I wanted to know when I was building the last tab, so that I could designate it as being selected (i.e., the one with the focus). The tab was already built by the time the loop ended, so I needed to know while inside of the loop (which was more efficient than using JavaScript to change the tab's properties after the fact).
I am creating a pagination script and I need to get the first and last results in the database query so that I can determine what results appear when the user clicks a page to go to. This is the code that I have at the minute:
// my database connection is opened
// this gets all of the entries in the database
$q = mysql_query("SELECT * FROM my_table ORDER BY id ASC");
$count = mysql_num_rows($q);
// this is how many results I want to display
$max = 2;
// this determines how many pages there will be
$pages = round($count/$max,0);
// this is where I think my script goes wrong
// I want to get the last result of the first page
// or the first result of the previous page
// so the query can start where the last query left off
// I've tried a few different things to get this script to work
// but I think that I need to get the first or last result of the previous page
// but I don't know how to.
$get = $_GET['p'];
$pn = $_GET['pn'];
$pq = mysql_query("SELECT * FROM my_table ORDER BY id ASC LIMIT $max OFFSET $get");
// my query results appear
if(!$pn) {
$pn = 1;
}
echo "</table><br />
Page $pn of $pages<br />";
for($p = 1;$p<=$pages;$p++) {
echo "<a href='javascript:void(0);' onclick='nextPage($max, $p);' title='Page $p'>Page $p</a> ";
}
I think you have few problems there, but I try to tackle them for you. First, as comments say above, you are using code that it vulnerable to SQL injection. Take care of that - you might want to use PDO, which is as easy use as MySQL extension, and will save you from many trouble (like injection).
But to your code, lets go through it:
You should ask DB to get count of the rows, not using mysql function, it's far more effective, so use SELECT count(*) FROM mytable.
For $pages use ceil() as you want all rows to be printed, if you have $max 5 and have 11 rows, round will make $pages 2, where you actually want 3 (last page just contains that last 11th row)
in LIMIT you want to LIMIT row_count OFFSET offset. You can calculate offset from page number, so: $max = row_count but $offset = ($max * $page) - $max. In your code if $get is directly the page, it means you get $get'th row (Not sure though what happens in your JS nextpage. Bare in mind that not all use JavaScript.)
I have prepared simple example here which uses PDO, maybe that gives you idea how simple it's use PDO.
The selecting rows shows example how to put parameters in SQL, it would be perfectly safe in this case state, 'SELECT * FROM pseudorows LIMIT '.$start.','.$max by I wanted to make an example how easy it is (and then safe):
// DB config
$DB_NAME = 'test';
$DB_USER = 'test';
$DB_PASSWD = 'test';
// make connection
try {
$DB_CONN = new PDO("mysql:host=localhost;dbname=".$DB_NAME, $DB_USER, $DB_PASSWD);
$DB_CONN->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die($e);
}
// lets say user param 'p' is page, we cast it int, just to be safe
$page = (int) (isset($_GET['p'])?$_GET['p']:1);
// max rows in page
$max = 20;
// first select count of all rows in the table
$stmt = $DB_CONN->prepare('SELECT count(*) FROM pseudorows');
$stmt->execute();
if($value = $stmt->fetch()) {
// now we know how many pages we must print in pagination
// it's $value/$max = pages
$pages = ceil($value[0]/$max);
// now let's print this page results, we are on $page page
// we start from position max_rows_in_page * page_we_are_in - max_rows_in_page
// (as first page is 1 not 0, and rows in DB start from 0 when LIMITing)
$start = ($page * $max) - $max;
$stmt = $DB_CONN->prepare('SELECT * FROM pseudorows LIMIT :start,:max');
$stmt->bindParam(':start',$start,PDO::PARAM_INT);
$stmt->bindParam(':max', $max,PDO::PARAM_INT);
$stmt->execute();
// simply just print rows
echo '<table>';
while($row = $stmt->fetch()) {
echo '<tr><td>#'.$row['id'].'</td><td>'.$row['title'].'</td></tr>';
}
echo '</table>';
// let's show pagination
for($i=1;$i<=$pages;$i++) {
echo '[ '.$i.' ]';
}
}
mysql_fetch_array returns an associative array
Which means you can use reset and end to get the first and last results:
$pqa = mysql_fetch_array($pq);
$first = reset($pqa);
$last = end($pqa);
I don't see how you plan to use the actual results, just page numbers should be sufficient for pagination.
Still, hope it helps. And yes, upgrade to mysqli, so your code doesn't get obsolete.
Here's what I've got so far-
$awards_sql_1 = mysql_query('SELECT * FROM categories WHERE section_id = 1') or die(mysql_error());
$awards_sql_2 = mysql_query('SELECT * FROM categories WHERE section_id = 2') or die(mysql_error());
$awards_sql_3 = mysql_query('SELECT * FROM categories WHERE section_id = 3') or die(mysql_error());
$awards_sql_4 = mysql_query('SELECT * FROM categories WHERE section_id = 4') or die(mysql_error());
$loop = 1;
while($row_sections = mysql_fetch_array($sections_query)) {
$category = 1;
echo "<h3>" . $row_sections['section_name'] . " (Loop# $loop)</h3>";
while($categories = mysql_fetch_array(${"awards_sql_{$loop}"})) {
${"winners_sql_{$loop}"} = mysql_query("SELECT * FROM 2009_RKR_bestof WHERE section = $loop && category = $category ORDER BY result_level ASC") or die(mysql_error());
echo "<h4><strong>{$categories['category_name']}</strong></h4>";
echo "<ul class=\"winners\">";
>> while($winners = mysql_fetch_array(${"winners_sql_{$loop}"})) {
switch ($winners['result_level']) {
case 1: $result_level = "Platinum"; break;
case 2: $result_level = "Gold"; break;
case 3: $result_level = "Silver"; break;
}
if (isset($winners['url'])) { $anchor = ""; $close = ""; }
echo "<li>$anchor{$winners['winner']}$close ($result_level)</li>";
unset($anchor);
unset($close);
}
echo "</ul>";
$category++;
}
$loop++;
}
Where I'm getting stumped, is I'm getting this thing to loop through correctly, my loop counter ($loop) is working, but when it gets time to spit out the actual reward recipients after the first loop through winners, it's only producing the category titles, the list-items are not getting looped out.
I added a little pointer to where I think the problem begins or centers around (>>).
My guess is I need to maybe unset a var somewhere, but I don't know, I can't see it.
I'm with KM - you're displaying a single page and with your loops, you've got a LOT of queries happening at once - what if 1,000 people hit that page at the same time? ouch...
Maybe consider a larger query (with some repeated data) and loop through it once?
For example:
SELECT
section_name,
category_name,
result_level,
url,
winner
FROM 2009_RKR_bestof
INNER JOIN categories ON 2009_RKR_bestof.category = categories.id
INNER JOIN sections ON 2009_RKR_bestof.section = sections.id
ORDER BY section_name,category_name ASC
In your loop, you can do checks to determine if you're in a new section (category/whatever):
//pseudo-code
$current_section = "";
while($stuff = mysql_fetch_array($sql))
{
if ($current_section == "")
{
$current_section = $stuff["section_name"];
}
if ($current_section == $stuff["section_name"])
{
//keep going in your loop
}
else
{
//we've gotten to a new section - so close your html and start a new section
}
}
You get the idea..
My guess would be that it is a data problem. It isn't having trouble reading the titles, only the winners. If it iterated once, I would check the data, and ensure that winners_sql_2 - winnders_sql_4 are getting actual data. Perhaps add an echo winners_sql_2 line, to output the contents of the query, and ensure the query is framed correctly.