PHP - Order a list of database elements - php

I am displaying a list of items based on a database. The order of the items is by ProductID.
When I add an item to the database, it is automatically assigned a ProductID.
However, I would like to be able to either
a) sort the list alphabetically by name, without changing the ProductID in the database or
b) add another column to the database called, for example: Rank, and have this list display the list by Rank, rather than by ProductID.
Here is my code. Any help in re-writing this section of the code to accomplish either a) or b) would be very helpful!
PS: I'm a little familiar with PHP and databases, but I am by no means an experienced coder.
$category = array_search(strtolower('upright'), $CFG["Category"]);
$product2 = new ProductData();
$where2 = sprintf(" WHERE CategoryID=%d ORDER BY ProductID DESC", $category);
$rows2 = $product2->GetRows($where2);
$count2 = count($rows2);
$line_count2 = 4;
$total_lines2 = ceil($count2/$line_count2);
// Photo
$photo5 = new PhotoData();
$thumb_array5 = array();
$count3 = count($rows2);
for ( $i = 0; $i < $count3; $i++ )
{
$ret = $photo5->Query($rows2[$i]["ProductID"]);
if ( $ret != 0 )
{
continue;
}
$thumb_array5[$photo5->Get("ProductID")] = $photo5->Get("Photo1");
}

Your SELECT query is not shown which I assume is coming from your ProductData() class. If you could change the source of your ProductData() that includes ranking, you could use a variable for ranking, like:
SELECT
#Ranking := #Ranking + 1 AS Rank,
productID,
product_name
FROM yourTable t, (SELECT #Ranking := 0) r
ORDER BY product_name;
Otherwise you could do it in your Php instead:
First change the ORRDER BY to your product name instead of product id:
$category = array_search(strtolower('upright'), $CFG["Category"]);
$product2 = new ProductData();
$where2 = sprintf(" WHERE CategoryID=%d ORDER BY Product_Name", $category);
Then in your php use a variable to do the ranking:
$count3 = count($rows2);
echo "<table><tr><th>Ranking</th><th>Product Name</th><th>Product Name</th></tr>";
for ( $rank = 0; $rank < $count3; $rank++ )
{
echo "<tr>";
echo "<td>$rank+1</td><td>".$rows2[$rank]["Product_name"]."</td><td><img src='".$photo5->Get("Photo1")."'></td>"
echo "</tr>";
}
echo "</table>";

Related

PHP array_sum outputs individual numbers rather than as a whole

I have this list of "coupons" each with a unique "productid"
Now I am trying to convert the list into an array using:
$claimed = array($rowOrder['productid']);
My issue is when I try to use "count" and "array_sum" it outputs individual numbers:
$count_claimed = array(count($claimed));
echo array_sum($count_claimed);
Using the echo I get and output of: "1111111"
What should I change to get a sum count of 7? (as displayed with the number of "coupons")
additional info:
The "coupons" are being outputted by this SELECT statement, $rowOrder is calling this.
public function SelectLst_ByUsrCustomerIDInfo($db, $usrcustomerid) {
$stmt = $db->prepare(
" SELECT o.orderid, o.productid, o.usrcustomerid, o.amount, o.amountrefunded, o.createddate, o.scheduleddate, o.useddate, o.expirationdate, p.photosrc
FROM `order` o LEFT JOIN `product` p ON o.productid = p.productid
WHERE usrcustomerid = :usrcustomerid"
);
$stmt->bindValue(':usrcustomerid', $usrcustomerid, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $rows;
}
This is called like this
$lstInfo = $mcOrder->SelectLst_ByUsrCustomerIDInfo($db, $usrcustomerid);
foreach($lstInfo as $rowOrder) {
if (isset($rowOrder['productid']) && ($rowOrder['expirationdate'] > date("Y-m-d H:i:s"))) {
$claimed = array($rowOrder['productid']);
$count_claimed = array(count($claimed));
echo array_sum($count_claimed);
}
}
Doing count($lstInfo) you will get the total number of fetched rows (PDOStatement::fetchAll() returns an array, and you just count the number of elements in it). Then you can loop the results and increment a variable called $claimed if the condition is true.
$lstInfo = $mcOrder->SelectLst_ByUsrCustomerIDInfo($db, $usrcustomerid);
$total = count($lstInfo);
$claimed = 0;
foreach($lstInfo as $rowOrder) {
if (isset($rowOrder['productid']) && ($rowOrder['expirationdate'] > date("Y-m-d H:i:s"))) {
$claimed += 1;
}
}
echo "Claimed $claimed of $total.";
Even better, you can do it in one query using a COUNT() and an added WHERE condition. This means you won't get the total, but that didn't seem to be the question to begin with either.
$stmt = $db->prepare("SELECT COUNT(productid) as cnt
FROM `order` o
LEFT JOIN `product` p
ON o.productid = p.productid
WHERE usrcustomerid = :usrcustomerid
AND expirationdate > NOW()
GROUP BY usrcustomerid");
$stmt->execute([":usrcustomerid" => $usrcustomerid]);
$result = $stmt->fetch();
echo "Claimed ".$result['cnt'];
Try This,
$claimed = array();
foreach($products as $rowOrder){
array_push($claimed,$rowOrder['productid']);
}
echo count($claimed);
echo array_sum($claimed);die;

Insert SQL query results into separate PHP variables

I'm trying to make an ad system with PHP pdo. How can I get result id's of the following SQL query into my PHP variables?
SELECT id FROM ads, ( SELECT id AS sid FROM ads WHERE position="A" ORDER BY RAND( ) LIMIT 5 ) tmp WHERE ads.id = tmp.sid
I just don't know how to get those values in the variables like this:
$ad_1 = result[1]
$ad_2 = result[2]
$ad_3 = result[3]
$ad_4 = result[4]
$ad_5 = result[5]
With the help of those variables ($ad_1...5) I could display unique and random ads in different places, get correct data, and update ad clicks/views...
Best to get into the habit of using prepared statements like this:
<?php
$adIds = array();
$position = 'A'; // probably set dynamicaly
$stmt = $dbh->prepare("SELECT id FROM ads, ( SELECT id AS sid FROM ads WHERE position=? ORDER BY RAND( ) LIMIT 5 ) tmp WHERE ads.id = tmp.sid");
$stmt->bindParam(1, $position);
if ($stmt->execute()) {
while ($row = $stmt->fetch()) {
$adIds[] = $row[0];
}
}
?>
$adIds is now an array containing all the ids returned from the select statement.
try this :
$begin = "ad_";
for($i = 0; $i < 6 ; $i++) {
$($begin.$i) = $result[$i];
}
(assuming you array $result is previously defined)

PHP array for loop

I want to show the array value $result[] from the for loop calculation. However, it shows me nothing on the page. Is there is anything wrong in the below code?
$sql= "SELECT * FROM items where itemID =3 ";
$result1= mysql_query($sql) or die (mysql_error());
while ($row= mysql_fetch_array($result1)){
$quantity[] = $row ['quantity'];
$month[] = $row ['month'];
}
$alpha = 0.3;
for($i = 1; $i > 12; $i++){
$result[$i] = ($quantity[$i] - $result[$i-1]) * $alpha + $result[$i-1];
}
foreach ($result as $key => $value ){
echo "$value";
}
Your for loop has an error. You have
for($i = 1; $i > 12; $i++)
but it should be
for($i = 1; $i < 12; $i++)
This is not directly the answer to your question, but there are few things that hasn't been mentioned that concern the way you query and process your data:
Your SELECT statement doesn't have specific order specified. Since order of records is not preserved you can get records out of correct order and get invalid calculations. Use ORDER BY (e.g. ORDER BY month) or make use of month values and extract exactly previous month's value from array(s) (if it is what you're doing in your code).
Your current code relies on the fact that the resultset from DB will contain (at least) 12 records. If for some reason it will produce less records your for loop will brake.
It's uncertain from the information in the question but it looks like you might need a year in your query unless the table contains records only for one year.
Now, you can calculate the whole thing on DB side with a query like this
SELECT i.month,
COALESCE((i.quantity - p.quantity) * 0.3 + p.quantity, 0) value
FROM items i LEFT JOIN items p
ON i.itemID = p.itemID
AND i.`year` = p.`year`
AND i.month = p.month + 1
WHERE i.itemID = 3
AND i.`year` = 2013
ORDER BY month
SQLFiddle
That's assuming (and I'm not sure about that) you actually need to read previous month's quantity values for your calculations and month column is of integer type
There is an obvious flaw in the logic. You try to get the $i index form $quantity. However, you can't be sure $quantity will have this index.
Supposing that itemId is not the primary key, I would do something like this:
$sql = "SELECT * FROM `items` WHERE `itemID` = 3";
$result1= mysql_query($sql) or die (mysql_error());
while ($row= mysql_fetch_assoc($result1)){
$quantity[] = $row ['quantity'];
}
$alpha = 0.3;
$i = 1
foreach ($quantity as $elem) {
if ($i >= 12)
break;
$result[$i] = ($elem - $result[$i-1]) * $alpha + $result[$i-1];
$i++
}
foreach ($result as $value ){
echo $value;
}

PHP MySql Swap value in two rows

I've seen a couple variations on this, but mainly they swap the entire row rather than just one value in that row, and not dynamically.
Here's the issue:
I have three rows each with the following cells (id, title, content, display_order, visible).
id is auto_increment. title and content are manually entered and visible is a toggle. display_order is set when each row is created and automatically set as the highest integer and set at the bottom of the stack.
I set it like this so that if any of these records were to be manually deleted, i can reorder the stack automatically (if there are 4 records, and I delete #2, the new order resets as 1,2,3 and not 1,3,4).
Each row has a set of up and down arrow buttons that call move.php with queries of id(id), display_order(pos) and direction(dir).
In the move.php it uses a conditional to determine whether to move the record UP or DOWN depending on what the direction variable is set at.
What PHP code do I need to write to take these three variables (id, pos, dir) and swap the value in the table cell display_order: Here's a visual representation
Initial:
id title pos
-----------------
1 slide1 1
2 slide2 2
3 slide3 3
After I click the UP button for record ID #3:
id title pos
-----------------
1 slide1 1
2 slide2 3
3 slide3 2
MIND YOU the ID and POS will not always be the same integer
USING davidethell's suggestion I have created this:
Here's what I have created, but all I'm getting is the echo $newPos rather that is going back to the admin.php:
require ("connection.php");
$id = $_GET['id'];
$pos = $_GET['pos'];
$dir = $_GET['dir'];
if ($dir == 'up') {
$newPos = $pos-1;
} else {
$newPos = $pos+1;
}
$fromRow = "SELECT * FROM pages WHERE display_order = ".$pos."";
$toRow = "SELECT * FROM pages WHERE display_order = ".$newPos."";
$reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $toRow['display_order'] . " WHERE id = " . $fromRow['id']."; UPDATE pages SET display_order = " . $fromRow['display_order'] . " WHERE id = " . $toRow['id']);
if ($reord){
header("Location: admin.php");
}else{
echo $newPos;
}
The problem I'm running into is that it only echos the $newPos
UPDATED CODE:
require ("connection.php");
$fromArray = array();
$toArray = array();
$id = $_GET['id'];
$pos = $_GET['pos'];
$dir = $_GET['dir'];
if ($dir == 'up') {
$newPos = $pos-1;
} else {
$newPos = $pos+1;
}
$fromRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$pos."");
$toRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$newPos."");
$reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $toRow['display_order'] . " WHERE id = " . $fromRow['id']);
$reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $fromRow['display_order'] . " WHERE id = " . $toRow['id']);
if ($reord){
header("Location: admin.php");
}else{
echo $newPos;
}
Result: echos the $newPos instead of return to admin.php
You could use this query:
UPDATE
yourtable INNER JOIN (
SELECT
MAX(yourtable.pos) pos_prec,
curr.pos pos_curr
FROM
yourtable INNER JOIN
(SELECT pos FROM yourtable WHERE id=3) curr
ON yourtable.pos<curr.pos
GROUP BY
curr.pos) cp ON yourtable.pos IN (cp.pos_prec, cp.pos_curr)
SET
pos = CASE WHEN pos=cp.pos_curr
THEN pos_prec ELSE pos_curr END
It's a little bit complicated, but it will swap the value of the position where ID=3 with the value of the position of the preceding item, even if there are gaps.
Please see fiddle here.
EDIT
If there are no gaps, you could simply use this to move ID#3 UP:
UPDATE
yourtable INNER JOIN (SELECT pos FROM yourtable WHERE id=3) curr
ON yourtable.pos IN (curr.pos, curr.pos-1)
SET
yourtable.pos = CASE WHEN yourtable.pos=curr.pos
THEN curr.pos-1 ELSE curr.pos END;
and just use +1 instead of -1 to move down (both UP and DOWN can be combined in one single query if needed).
PHP Code
And this is using PHP and mysqli, and assuming that the position is given:
<?php
$mysqli = new mysqli("localhost", "username", "password", "test");
$pos = 3;
$dir = 'down';
if ($dir == 'up') { $newPos = $pos-1; } else { $newPos = $pos+1; }
if ($stmt = $mysqli->prepare("
UPDATE
yourtable
SET
pos = CASE WHEN yourtable.pos=?
THEN ?
ELSE ? END
WHERE
pos IN (?, ?)
AND (SELECT * FROM (
SELECT COUNT(*) FROM yourtable WHERE pos IN (?,?)) s )=2;"))
{
$stmt->bind_param("iiiiiii", $pos, $newPos, $pos, $pos, $newPos, $pos, $newPos);
$stmt->execute();
printf("%d Row affected.\n", $stmt->affected_rows);
$stmt->close();
}
$mysqli->close();
?>
(i also added a check, if trying to move UP the first pos, or DOWN the last one it will do nothing).
Assuming a $row object with each row data, just do:
if ($dir == 'up') {
$fromRow = $row2;
$toRow = $row1;
}
else {
$fromRow = $row1;
$toRow = $row2;
}
$sql = "UPDATE mytable SET pos = " . $toRow['pos'] . " WHERE id = " . $fromRow['id'];
// now execute your SQL however you want in your framework
$sql = "UPDATE mytable SET pos = " . $fromRow['pos'] . " WHERE id = " . $toRow['id'];
// now execute your SQL however you want in your framework
Put that in a function or class of some kind to make it reusable.
EDIT:
Based on your edits it looks like you are not fetching enough information in your queries. They should be:
$fromRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$pos."");
$toRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$newPos."");
You were only selecting the id field, but then you were trying to use the display_order field.
i will not write you the PHP code. But i will give you the SQL:
Let's say $delta is either +1 if the slide's position should be raised 1, or -1 if the slide's position should be lowered by 1.
$id is the id of the slide. Ow, and let's assume the table is called slides_table.
You will need 2 queries:
update slides_table set pos = pos + $delta where id = $id;
update slides_table set pos = pos - $delta where pos = (select pos from slides_table where id=$id) and id != $id

Sorting a MySQL query with ORDER BY or with PHP sort functions

I have a query that I want to sort alphabetically, but the trick is that I want the sorting to treat two columns equally. For instance, if the first row of first_col equals apple and the second row of second_col equals aardvark I want the value in the second row of second_col to be listed before the value in the first row of first_col. A value (not NULL or '') will always exist in every row of second_col, but the value in first_col can be ''. Hopefully I have explained this good enough. I don't care if I have to use MySQL or PHP for this, but once sorted, the array is read through and echoed into an HTML table. Any thoughts?
EDIT
This is what I have for code right now. In my MySQL query I need b_name and l_name to be equal. The column b_name does not always have a value. When I put the values into the table it is based on the existence of b_name. If b_name does not exist the f_name and l_name are combined to replace b_name.
$query = "SELECT * FROM customers ORDER BY b_name, l_name";
$result = mysql_query($query);
mysql_close($link);
$num = mysql_num_rows($result);
for ($i = 0; $i < $num; $i++){
$row = mysql_fetch_array($result);
$class = (($i % 2) == 0) ? "table_odd_row" : "table_even_row";
if($row[b_name]!=''){
echo "<tr class=".$class.">";
echo "<td>".$row[c_id]."</td>";
echo "<td>".$row[b_name]."</td>";
echo "<td>".$row[phone]."</td>";
echo "</tr>";
}
else{
echo "<tr class=".$class.">";
echo "<td>".$row[c_id]."</td>";
echo "<td>".$row[f_name]." ".$row[l_name]."</td>";
echo "<td>".$row[phone]."</td>";
echo "</tr>";
}
}
?>
</table>
If your tables are very similar you can do this
In my case I have a table test_a with 2 columns id and name
(SELECT * FROM test_a a1)
UNION ALL
(SELECT * FROM test_a a2)
ORDER BY name DESC
Your question isn't completely clear but you could try using this as your ORDER BY clause:
ORDER BY LEAST(first_col, second_col)
Demonstration:
CREATE TABLE table1 (first_col VARCHAR(100) NOT NULL, second_col VARCHAR(100) NOT NULL);
INSERT INTO table1 (first_col, second_col) VALUES
('a', 'b'),
('d', 'e'),
('f', 'c');
SELECT first_col, second_col
FROM table1
ORDER BY first_col, second_col;
a b
d e
f c
SELECT first_col, second_col
FROM table1
ORDER BY LEAST(first_col, second_col);
a b
f c
d e
Try
ORDER BY CONCAT(b_name, l_name)
or (if your fields are NULL when EMPTY)
ORDER BY COALESCE(b_name, l_name)
As they say above, UNION ALL is your friend, and, of course, if you have only one table, you can always do this:
(SELECT field1 AS name FROM TABLE1)
UNION ALL
(SELECT field2 AS name FROM TABLE1)
ORDER BY name DESC
So, you are asking for two diferent rows in the same table, and ordering it as it was one.
Thanks for all your help guys, but none of your answers allowed me to sort the data AND echo it into the HTML table correctly once sorted. A UNION might have worked, but I think my solution was faster as far as figuring it all out goes.
$query = "SELECT c_id, b_name, l_name, f_name, phone FROM customers";
$result = mysql_query($query);
mysql_close($link);
$num = mysql_num_rows($result);
for ($i = 0; $i < $num; $i++){
$row = mysql_fetch_array($result);
if($row[b_name]!=''){
$new_result[$i]['c_id'] = $row[c_id];
$new_result[$i]['c_name'] = $row[b_name];
$new_result[$i]['phone'] = $row[phone];
}
else{
$new_result[$i]['c_id'] = $row[c_id];
$new_result[$i]['c_name'] = $row[l_name].", ".$row[f_name];
$new_result[$i]['phone'] = $row[phone];
}
}
foreach ($new_result as $key => $row) {
$c_id[$key] = $row['c_id'];
$c_name[$key] = $row['c_name'];
$phone[$key] = $row['phone'];
}
array_multisort($c_name, SORT_ASC, $c_id, SORT_ASC, $new_result);
for ($i = 0; $i < $num; $i++){
$class = (($i % 2) == 0) ? "table_odd_row" : "table_even_row";
echo "<tr class=".$class.">";
echo "<td>".$new_result[$i]['c_id']."</td>";
echo "<td>".$new_result[$i]['c_name']."</td>";
echo "<td>".$new_result[$i]['phone']."</td>";
echo "</tr>";
}
?>
</table>

Categories