How to create an alphabetized drop down menu in PHP - php

I'm trying to re-write this code so that the drop down menu is alphabetized:
$activeProjectDropdown.="<option value=''>Select Project</option>";
$getInfo = "SELECT id, customer, job_name, haul_info
FROM dispatch_jobs
WHERE (:mydate BETWEEN delivery_date AND delivery_date_end)
ORDER BY customer, job_name";
$result=DB::run($getInfo, ['mydate' => $myDate]);
while($row=$result->fetch(PDO::FETCH_BOTH)) {
if(!empty($row['haul_info'])) {
$haulinfo = "($row[haul_info])";
}else{
$haulinfo = "";
}
if($checkit == $row['id']){
$woot = 'selected=selected';
}else{
$woot = '';
}
$customerName = pdo_getName('name', 'customer', "$row[customer]");
$activeProjectDropdown.="<option value='$row[customer]|$row[id]' $woot>$customerName $haulinfo</option>\n";
}
In this code the query returns some rows from the database where customer is a numeric code which isn't in any kind of alphabetical order. Further down in the code a function called pdo_getName is called which takes a column of name table of customer and the id from $row['customer'] and queries the database, returning the stringified name of the customer. Because the name isn't being retrieved until later on down the loop I'm having trouble figuring out a way that I can alphabetize the $activeProjectDropdown. I've tried putting the $customerName and drop down code into an associative array, then sort that by $customerName and concat everything into a string, but that didn't work because there are duplicate keys. Down that same path, I could potentially have a nested array but I figure there must an easier solution I'm missing. Thanks for the help!

write a JOIN query and get all the data in one query then you can sort on the customers name as I think you are asking to do.
This will improve performance as well as simplify the code.
$getInfo = "SELECT dj.id, dj.customer, dj.job_name, dj.haul_info
c.name
FROM dispatch_jobs dj
LEFT JOIN customer c ON c.id = dj.customer
WHERE (:mydate BETWEEN dj.delivery_date AND dj.delivery_date_end)
ORDER BY c.name, dj.job_name";
$result=DB::run($getInfo, ['mydate' => $myDate]);
while($row=$result->fetch(PDO::FETCH_BOTH)) {
if(!empty($row['haul_info'])) {
$haulinfo = "($row[haul_info])";
}else{
$haulinfo = "";
}
if($checkit == $row['id']){
$woot = 'selected=selected';
}else{
$woot = '';
}
$activeProjectDropdown.="<option value='$row[customer]|$row[id]' $woot>$row[name] $haulinfo</option>\n";
}

Try this:
SELECT ... ORDER BY customer ASC, job_name
This sorts everything by costumer (ascending) first, and then by job_name (ascending, which is the default) whenever the costumer fields for two or more rows are equal.
more info here

Related

SELECT a value multiple time in SQL

I have a code in PHP where I want to display multiple times values, and so, even if these values are the same between them. My code is simple :
$sql = "SELECT photo from table WHERE username IN ('1','2','2') ORDER BY id DESC ";
$res = array();
$result = mysqli_query($con,$sql);
while($row = mysqli_fetch_array($result)){
array_push($res, $row['photo']);
}
echo json_encode($res);
But this code only display (in json) an array of two values (because the values of photo of the username 2 are the same).
What I want to achieve is to make an array with the exact same number of values of the number of username I defined WHERE username IN ('1','2','2') (so here, 3 values).
I hope you understood me, thanks for helping me !
I think what you're after is to list even the duplicates in the end result. As your SQL will only retrieve the unique items, the idea would be to include the username in the SQL result set. Then use the original list of user names ($userNames) and add in the photo for each of them.
I've used mysqli_fetch_all() to simplify the process of fetching all of the data, then used array_column() to make the username the key for the photos.
$userNames = array(1,2,2);
$sql = "SELECT username, photo
from table
WHERE username IN ('".implode("','", $userNames)."')
ORDER BY id DESC ";
$res = array();
$result = mysqli_query($con,$sql);
$photos = mysqli_fetch_all($result, MYSQLI_ASSOC);
$photos = array_column($photos, "photo", "username");
foreach ( $userNames as $user ) {
if ( isset($photos[$user])) {
$res[] = $photos[$user];
}
else {
$res[] = '';
}
}
echo json_encode($res);
You would use left join:
select t.photo
from (select '1' as username union all select '2' union all select '3'
) u left join
table t
on t.username = u.username
order by t.id desc;
Note this will return rows, even when the user name does not exist. If you want to filter those rows, remove the left so you are doing an inner join.

SQL query to get value from referenced table

I have two tables called mg_product and mg_product_user_property.
In mg_product there are 3 columns: id, title, price as
In mg_product_user_property table product_id corresponds with id column in mg_product table.
So my goal is to get the value of property_id of "15", which in the picture above will be "Mediatek".
This is my SQL:
$sql = "SELECT *
FROM mg_product AS products
INNER JOIN mg_product_user_property AS properties
ON products.id = properties.product_id
WHERE title LIKE '%$search%')";`
PHP:
$resultSet = DB::query($sql);
if ($resultSet->num_rows > 0) {
while ($rows = $resultSet->fetch_assoc()) {
$title = $rows['title'];
$price = $rows['price'];
}
} else {
$output = "No results";
}
Now I need to assign to a php variable the value of property_id=15 so I will be able to print "Mediatek" on my website. How can I achieve that? Sorry for my English.
You are pretty close to what you want, but a couple things are going to either be a mess, or unwanted. So, since there are different ways one can go with this, I will only present a very stripped example (and am INTENTIONALLY leaving out a bunch of code here).
You may not want to do a JOIN like that in the initial search, as for each property, it will also return another of the same product. So looping through that will result in dozens of the same product.
However, if _ALL_YOU_WANT_ is to show the Product Title, Price, and Property 15... you can reduce some headwork with a simpler query:
SELECT p.title, p.price, pr.value
FROM mg_product AS p
LEFT JOIN mg_product_user_property AS pr
ON p.id = pr.product_id AND pr.property_id = 15
WHERE p.title LIKE '%$search%'
The LEFT JOIN means if the property doesn't exist, it will still return the product. But with an empty property value. And this should not return dozens of the same product for every other property in the table.
--
The OTHER way you could go about doing it, using the SQL query you already have (and the dozens of results of the same product it will return), you can alter your php loop like so:
$found_products = array();
while ($row = $resultSet->fetch_assoc()) {
if ($row['property_id'] == 15) {
$found_products[$row['product_id']] = array(
'title' => $row['title'],
'price' => $row['price'],
'prop' => $row['value']
);
}
}
// now you have a clean array of found products that have the property
--
Also I am forced to point out that you should use a prepared statement here, replacing inserting $search directly into the code. But showing you all of how to do that is beyond the scope of this question/answer.

How to return only items that occur in 2 sql select statemnts

I have two different sql statements. $sql grabs all the items whose title matches a certain search text. $cat_sql grabs all the category_items that are in a certain category. An item has an ID. A category_item has a field called item_id which is a foreign key to IDs in the items table
...
mysqli setup code
...
$title = $_POST["title"];
$cat_id = $_POST["cat_id"];
$cat_sql = "SELECT * FROM category_items WHERE category_id = '".$cat_id."'";
$sql = "SELECT * FROM items where title LIKE '%". $title ."%' Limit 70";
if (!$result_cat = $mysqli->query($cat_sql)) {
// The query failed.
echo "<h2 >ERROR</h2>";
exit;
}
if (!$result = $mysqli->query($sql)) {
// The query failed.
echo "<h2 >ERROR</h2>";
exit;
}
Then I display all items:
while ($item = $result->fetch_assoc()) {
include 'item_card.php';
}
Currently this just displays all items fetched in the $sql query. Is there some way to remove all items from $result that do not have their ID represented as an item_id in $result_cat?
NOTE:
I would strongly prefer not to do just combine both SELECT statements into a table join because the actual $sql and $cat_sql are not nearly as simple as I have represented here. Also, they vary depending on which if statement they are in.
My question is: given $result and $result_cat, can I remove items from $result?
EDIT 1
As suggested by comments I am making an array if item_ids then doing an in_array query. Progress thus far:
$result_cat_ids = [];
while ($cat_item = $result_cat->fetch_assoc()) {
$result_cat_ids[] = $cat_item['item_id'];
}
EDIT 2 Here is the working code following the suggestions in the comments
if (in_array($item['id'], $result_cat_ids)) {
include 'item_card.php';
}
You may also use 'INTERSECT' sql clause.
$sql = "SELECT * FROM items WHERE id IN (SELECT item_id FROM category_items WHERE category_id = '".$cat_id."' INTERSECT SELECT id FROM items where title LIKE '%". $title ."%')";
This way, you can query for items that accomplish both conditions.
Note: I'm not using "limit 70" but you may add it as well.

Combine the results of multiple select

I need your help with a small thing. I have two tables I need to get a list of the names and IDs of the people from the first table. Then use this list to get the services associated to these people.
Please keep in mind that I need both the name and ID to identify the service.
The query is similar to the following:
$query = "SELECT id, name from person where customerType='specificType';
$result = mysql_query($query,$this->connection);
After that I loop through the result of this query to get the services list:
While ($list=mysql_fetch_array($result))
{
$query = "SELECT serviceID, serviceName from services
where assignedToName='".$list['name']."' and assignedToID=".$list['id'];
$result2 = mysql_query($query,$this->connection);
if(!$result2 || mysql_num_rows($result2) <= 0)
{//I do nothing}
else{
if(isset($servicesList))
{
//Here is the part that is not working, How to combine the results??
$servicesList .= $result;
}
else $servicesList=$result;
}
}
//End While
if(isset($servicesList))
{ return $servicesList;}else {
return 'error';
}
Thanks in advance...
Please consider using a join and just one query.
Something like this:
SELECT
p.id,
p.name,
s.serviceID,
s.serviceName
FROM
person p
LEFT JOIN
services s
ON
(p.id = s.assignedToID
AND
p.name = s.assignedToName)
WHERE
p.customerType='specificType'

MySQL: printing data just once for each grouping

I'm coding in PHP/MySQL and have the following query to fetch products and product group data:
SELECT products.id,products.name,product_groups.id,product_groups.name
FROM products
INNER JOIN product_groups
ON products.id=product_groups.id
WHERE products.name LIKE '%foobar%'
ORDER by product_groups.id ASC
So this query fetches products and orders them by product group. What I would like to have is to display product_groups.name just once for each product grouping. So even if I have ten shoe products, the group name "Shoes" is only displayed once.
I'm using the following PHP to print out the results:
while ($data = mysql_fetch_array($result))
If you want it done in the MySQL query, it is honestly more trouble than it's worth. For one, the syntax is really wonky (as I recall) to have a group name listed at the top of each grouping. And the results are still treated as rows, so the group name will be treated like a row with all the other columns as Null, so you won't really save any time or effort in the PHP script as it has to do an if statement to catch when it hits a group name instead of the group data.
If you want it done by the PHP while loop, Johan is on the right track. I use the following for a similar situation:
$result = $sql->query($query);
$prev_group = "";
while($data = $result->fetch_assoc()){
$curr_group = $data['group'];
if ($curr_group !== $prev_group) {
echo "<h1>$curr_group</h1>";
$prev_group = $curr_group;
}
else {
echo $data;
.....
}
Obviously the echo data would be set up to echo the parts of the data the way you want. But the $prev_group/$curr_group is set up so that the only time they won't match is when you are on a new group and thus want to print a header of some sort.
while($data = mysql_fetch_assoc($result)){
if($data['product_groups.name'] != $groupname){
echo "Groupname: ".$data['product_groups.name']."<br />";
$groupname = $data['product_groups.name'];
}
echo "ID: ".$data['products.id']."<br />";
echo "Name: ".$data['products.name']."<br />";
}
Maybe you can do like this!?

Categories