I have a page that's suppose to create a Div for every 9 entries in the database.
Every Div will consist of 3 ULs and every UL will consist of 3 LIs.
Something like this:
Demo
So, every LI is where each entry is displayed and every Div is essentially a unique page.
This is my code so far:
$sql = mysql_query("SELECT * FROM `reviews`") or die(mysql_error());
$e_count = mysql_num_rows($sql);
$r_pages = ceil($e_count / 9);
$x = 1;
$y = 1;
if($e_count > 9){ // if there are more than 9 entries in the database
for($x=1;$x<=$r_pages;$x++){ // creates a div for every 9 items in the database
echo '<div class="rp_pages" id="rp_page_'.$x.'">';
for($y=1;$y<=3;$y++){ // creates 3 ULS in each "page"
echo '<ul>';
// 3 lis should appear here
echo '</ul>';
}
echo '</div>';
}
}
The problem is, i don't want to use multiple queries with a LIMIT in them to select the respective entries.
Can this be done with just a single query?
I only see one query (the first select). After that, instead of using it to count the number of rows, parse each row and extract the review text, this way:
Let's imagine that the reviews table has a text column where the review text is saved. Having your code:
$sql = mysql_query("SELECT * FROM `reviews`") or die(mysql_error());
$e_count = mysql_num_rows($sql);
$r_pages = ceil($e_count / 9);
$x = 1;
$y = 1;
if($e_count > 9){ // if there are more than 9 entries in the database
for($x=1;$x<=$r_pages;$x++){ // creates a div for every 9 items in the database
echo '<div class="rp_pages" id="rp_page_'.$x.'">';
for($y=1;$y<=3;$y++){ // creates 3 ULS in each "page"
echo '<ul>';
// Here the code that extract the rows from the query.
for($z=1;$z<=3;$z++){
echo '<li>';
if($data = mysql_fetch_array($sql, MYSQL_ASSOC)) {
echo $data['text']; // Use some type of parser to show special characters like < or > as text, so you are safe from code injection.
}
echo '</li>';
}
echo '</ul>';
}
echo '</div>';
}
}
As you can see, it creates a new loop to create the 3 lis and in each li extracts the text selected in the query, then echoes it.
As http://php.net/manual/en/function.mysql-fetch-array.php says:
Returns an array that corresponds to the fetched row and moves the
internal data pointer ahead.
So the next time you fetch a row, it will be the next one.
PD: PHP's mysql is deprecated. Use mysqli instead. Is the same but with another library that is currently under developement, not like mysql.
Related
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).
Say I have a query the following query run:
Edit
Added order clause because the real sql statement has one.
SELECT description, amount, id FROM table ORDER BY id
In this instance, the ID is not unique to the dataset. It would return something like this.
Description Amount ID
----------- ------ --
1 Hats 45 1
2 Pants 16 1
3 Shoes 3 1
4 Dogs 5 2
5 Cats 6 2
6 Waffles 99 3
What I need to do is enclose each section of IDs in it's own div (So rows 1,2,3 in one div, 4,5 in another div and 6 in it's own div).
There are tons of solutions to this but I just can't think of one that isn't overly complicated.
I want to be able to keep the SQL how it is and somehow sort the data set in PHP so that I can loop through each section of the dataset while looping through the dataset as a whole.
Some kind of array would work but the structure of it is stumping me.
How can I get this to work? PHP solutions would be idea but theoretical will help too.
See if something like this works for you.
// execute query: Select description, amount, id from table
$results = array();
while ($row = $query_result->fetch_array()) {
if (!isset($results[$row['id']])) $results[$row['id']] = array();
$results[$row['id']][] = $row; // push $row to results for this id
}
// later on
foreach($results as $id => $data) {
// output div based on $id
foreach($data as $datum) {
// output individual data item that belongs to $id
}
}
A simple serial solution might look something like this:
$curId = ''; // track working id
$firstDiv = true; // track if inside first div
// open first div
echo '<div>';
// foreach $row
{
// when id changes, transition to new div, except when in first div
if ($row->$id != $curId) {
if ($firstDiv) {
$firstDiv = false;
} else {
// start new div
echo '</div>';
echo '<div>';
}
$curId = $row->$id; // track new current id
}
// display contents of current row
}
// close last div
echo '</div>';
Just store the id in temp variable, if the next one is different close the div and open new div
Assuming associative arrays for the db results:
$final = array();
foreach($results as $result)
{
$final[$result['id']][] = $result;
}
This leaves you with an associative array $final that groups the entries by ID
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.
I have a while loop that displays result from a MySQL query. I know how to change the output for the last row or an odd row but how can I change the output for the last two results?
For example I have a list of results in a 2x2 matrix with border-bottom: 1px on each result but I would like to display the bottom two without the border?
If you can use css3, it´s easy (I´ll use a list for the example):
li:nth-last-child(-n+2)
selects the last two li's.
If you want to do it in php, you can count the number of results, add a counter in your loop and add a class to the last two items.
Yeah just do it like this:
$result = //execute your query
$num_rows = mysql_num_rows($result;
$num_rows_different = 2;
$loop_counter = 0;
while ($loop_counter < $num_rows) {
if ($loop_counter < $num_rows - $num_rows_different) {
// with border
} else {
// no border
}
$loop_counter++;
}
I wouldn't use the CSS3 method due to its poor support...
I like the CSS way, but you'll need to know the total number of items you're listing. Then you can use a simple condition to check for that.
$total_items = [count of items];
$cnt = 0;
while($fetch as $row) {
...
if(++$cnt > ($total_items - 2)) {
// list with no border
} else {
// list with border
}
}
Been all over the place and spent 8 hours working loops and math...still cant get it...
I am writing a CP for a customer. The input form will allow them to add a package deal to their web page. Each package deal is stored in mysql in the following format
id header item1 item2 item3...item12 price savings
The output is a table with 'header' being the name of the package and each item being 1 of the items in the package stored in a row within the table, then the price and amount saved (all of this is input via a form and INSERT statement by the customer, that part works) stored rows as well.
Here is my PHP:
include 'dbconnect.php';
$query = "SELECT * FROM md ";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
//Print 4 tables with header, items, price, savings
//Go to next row (on main page) and print 4 more items
//Do this until all tables have been printed
}
mysql_free_result($result);
mysql_close($conn);
Right now the main page is simpley a header div, main div, content wrap and footer div.
Ideal HTML output of a 'package' table, not perfect and a little confusing
$header
$item1
$item2
ect...
$price$savings
I basically want the PHP to print this 4 times per row on the main page and then move to the next row and print 4 times and continue until there are no more items in the array. So it could be row 1 4 tables, row 2 4 tables, row 3 3 tables.
Long, confusing and frustrating. I about to just do 1 item per row..please help
Jake
You say "tables", but do you mean cells?
The basic flow would be:
$res = mysql_query(...) or die(mysql_error());
if (mysql_numrows($res) == 0) {
... say there's nothing to show ...
} else {
... print table header ...
while($row = mysql_fetch_assoc($res)) {
... print row ...
}
... print table footer
}
if i get your question right you need to use a loop, something like a for
while ($row = mysql_fetch_array($result)) {
for($i=1; $i<=3; $i++){
//print table (change $i values to change number of loops)
}
}
if i didnt get it right, please post an example of how the table should look like.
$items_per_line=4;
$counter=$items_per_line;
while ($row = mysql_fetch_array($result)) {
if($counter <1){
$counter=$items_per_line;
// goto next pages
}
// print header etc.
$counter--;
}