I'm trying to imitate how the Windows "Map Network Drive" dropdown works. My dropdown options are the letters A-Z. Based on the results from my SQL SELECT statement, I need to show but disable those letters that are already in use. I'm able to get the letters in the dropdown, or get my SQL results in the dropdown but not the correct combination of both.
How do I display all letters of the alphabet in a dropdown and disable those that come back in my SQSL SELECT statement?
Example DB
ID | Desc
-----------
A | Desc A
D | Desc D
F | Desc F
J | Desc J
Z | Desc Z
So for example, using the example DB above, the letters 'A, D, F, J, Z' would be displayed but disabled whereas all other letters in the alphabet would be selectable.
This is the code I currently have. It's very close to being correct but somehow out of order. It does display every letter of the alphabet and my database results (with those results disabled) BUT every letter of the alphabet is displayed for every database result. Again using the Example DB above, the code below would display the letters 'A' through 'Z' for each result (5 times) and each time disable that result only.
<select>
<?php
// SQL select from Example DB table and connection
while ($row = odbc_fetch_array($db)) {
foreach (range('A', 'Z') as $value) {
if ($row['id'] == $value) {
$result = $value.' -- '.$row['desc'];
$dis = "disabled";
} else {
$result = $value;
$dis = "";
}
?>
<option <?php echo $dis; ?>><?php echo $result; ?></option>
<?php
}
}
?>
</select>
I've tried moving the 'while' and 'foreach' around but haven't seemed to get them in the correct order.
You need to first query your database for letters in use, and then create a looping statement that goes from A to Z, and either marks the <option> as disabled or not.
<?php
$inUse = array();
$sql = "SELECT UNIQUE(`ID`) FROM `table` ORDER BY `ID` ASC";
$res = $db->query($sql);
foreach ($drive as $res->fetchObject()) {
$inUse[] = $drive['ID'];
}
// create select list
echo '<select name="drive">';
foreach (range('A', 'Z') as $letter) {
$disabled = (in_array($letter, $inUse)) ? ' disabled="disabled"' : '';
echo '<option value="' . $letter . '"' . $disabled . '>' . $letter . '</option>';
}
echo '</select>';
Untested, but you could try this:
<select>
<?php
$range = range('A', 'Z');
$used = array();
// Fill in used drives along with their descriptions
while ($row = odbc_fetch_array($db)) {
$used[$row['ID']] = $row['desc']);
}
foreach ($range as $value) {
$result = $value;
$dis = "";
if (in_array($value, $used) {
$result .= ' -- '.$used[$value];
$dis = 'disabled="disabled"';
}
?>
<option <?php echo $dis; ?>><?php echo $result; ?></option>
<?php
}
?>
</select>
Related
I have seven columns representing days of the week in a user table 'team' storing the indices from nine daily ranges from which the user selects. Table timerange range uses the index rangeID. The user chooses from a multiple select list one or more timeranges and the indices are stored for that day as in comma delimited list:
+------+-------+---------+
|sun + mon + tue +
|-------+-------+---------+
|2,4,5 + 1,3 + 9 +
+------+-------+---------+
My challenge is to return a div table of the same presentation of that used to select the date ranges but with the selected options highlighted (selected) so that the user's availability can be displayed and or edited in the form.
I have attempted to get that result with the following query for one day, Sunday, but am failing with the result that while the selected options display correctly, each of the choices not selected displays twice in the select lst:
echo "<select multiple=\"multiple\" size=\"10\" name=\"sun[]\">";
echo "<option size=\"30\"></option>";
$sql = "SELECT sun, rangeID, timeranges FROM test, timerange ORDER BY rangeID";
foreach ($myconnect->query($sql) as $row) {
$index=explode(',', $row['sun']);
foreach($index as $sun) {
if ($row['rangeID']==$sun) {
echo "<option selected=\"selected>\" value='" . $row['rangeID'] . "'>" . $row['timeranges'] . "</option>";
} else {
echo "<option value='" . $row['rangeID'] . "'>" . $row['timeranges'] . "</option>";
}
}
}
echo "</select>";
Somewhere logic is failing me so I'd like help in correcting the code so that only the nine time ranges are displayed with zero, one or more options selected.
After a week of all sorts of gymnastics with code, adding to my gray hairs, I arrived at a solution that is not elegant but is fine since the action is to be called by one user (at a time) to pre-populate a form. It beats creating multiple tables, which will have many empty rows, to store 0-9 indexes of nine indexes. I'll definitely work on a more efficient table structure for storing the user-selected data and querying one or multiple users at a time.
$sql = "SELECT sun FROM test";
foreach ($myconnect->query($sql) as $days)
{
$index = explode(',', $days['sun']);
}
echo "<select multiple=\"multiple\" size=\"9\" name=\"sun[]\">";
$sql = "SELECT rangeID, timeranges FROM timerange ORDER BY rangeID";
foreach ($myconnect->query($sql) as $row)
{
$arr = array_merge($index, $row);
if ($row['rangeID'] == # $arr[0] or # $arr['rangeID'] == # $arr[1] or $row['rangeID'] ==
# $arr[2] or $row['rangeID'] == # $arr[3] or $row['rangeID'] == # $arr[4] or $row[
'rangeID'] == # $arr[5] or $row['rangeID'] == # $arr[5])
{
$selected = "selected=\"selected\"";
}
else
{
$selected = "";
}
echo "<option value=" . $row['rangeID'] . " " . $selected . ">" . $row['timeranges'] .
"</option>";
}
echo "</select>";
Using while loop, i can get all the result in the table and echo it into a html table.
But, i want to skip the first row, and echo the result starting from second row.
How can i do that?
This is my code.
$sql2="select * from table where year = '2015' and month = '2' order by month desc";
$result2=mysqli_query($conn,$sql2);
echo '<table>';
while($row2=mysqli_fetch_assoc($result2))
{
echo '<tr>';
echo '<th>'.$row2['acc_sth_date'].'</th>';
echo '<th>'.$row2['acc_sth_med_ori'].'</th>';
echo '<th>'.$row2['acc_sth_med_new'].'</th>';
echo '<th>'.$row2['acc_sth_operator'].'</th>';
echo '</tr>';
}
echo '</table>';
Help me please master. Thanks
You can achieve that in two ways.
You could use LIMIT statement in your sql query :
$sql2="select * from table where year = '2015' and month = '2' order by month desc LIMIT 1,100";
1 = Start at the 2nd row
100 = Returns a maximum of 100 rows
Add a condition in your while loop :
$firstRow = true;
while ($row2 = mysqli_fetch_assoc($result2))
{
if (true === $firstRow)
{
$firstRow = false;
continue;
}
// ... Rest of your code ...
}
You need to add a variable that is tested and set to true to not allow skipping next time:
$FirstRun=true;
while($row2=mysqli_fetch_assoc($result2))
{
if ($FirstRun){
$FirstRun = false;
}else {
echo '<tr>';
echo '<th>'.$row2['acc_sth_date'].'</th>';
echo '<th>'.$row2['acc_sth_med_ori'].'</th>';
echo '<th>'.$row2['acc_sth_med_new'].'</th>';
echo '<th>'.$row2['acc_sth_operator'].'</th>';
echo '</tr>';
}
}
Use the following code
$sql2="select * from table where year = '2015' and month = '2' order by month desc";
$result2=mysqli_query($conn,$sql2);
$row2=mysqli_fetch_assoc($result2);
$count = count($row2);
$i = 1;
echo '<table>';
while(i>=$count)
{
echo '<tr>';
echo '<td>'.$row2[i]['acc_sth_date'].'</td>';
echo '<td>'.$row2[i]['acc_sth_med_ori'].'</td>';
echo '<td>'.$row2[i]['acc_sth_med_new'].'</td>';
echo '<td>'.$row2[i]['acc_sth_operator'].'</td>';
echo '</tr>';
$i++;
}
echo '</table>';
It will display all rows except the first row.
If I query a database with PHP using MySQLi, how can I detect the first instance of each letter of the alphabet?
If I have a table like -
ID | name
1 Allen
2 John
3 Sally
4 William
and I query
SELECT * FROM table ORDER BY name ASC
Can I have something in my loop that says "if this is the first time you've seen the string in name start with the letter A", echo <a id="a"></a> to create an anchor tag? Then it will proceed to do the same for B,C,D,E,F,G, etc.. Then I can create an alphabetical legend.
Here is my query and loop:
$query = "SELECT * FROM table ORDER BY name ASC";
$result = $db->query($query);
$num = $result->num_rows;
for($i=0; $i < $num; $i++){
$row = $result->fetch_object();
//IF THIS IS THE FIRST TIME SEEING $row->name START
//WITH A DIFFERENT LETTER OF THE ALPHABET ECHO SOMETHING...
echo $row->name;
}
Create an associative array that records which letters you've seen.
$letters_seen = array();
while ($row = $result->fetch_object()) {
$letter = substr($row->name, 0, 1);
if (!isset($letters_seen[$letter])) {
// This is the first time seeing this initial letter
$letters_seen[$letter] = true;
echo "<a id='$letter'>$letter</a>";
}
echo $row->name;
}
Since your results are ordered by name, if the first letter of the current row doesn't match the first letter of the previous row, then you know it's the first time you've seen it.
$previousLetter = '';
for($i=0; $i < $num; $i++){
$row = $result->fetch_object();
if($row->name[0] != $previousLetter) {
echo "<a id='" . $row->name[0] . "'></a>";
$previousLetter = $row->name[0];
}
echo $row->name;
}
I'm using below code to display Image & Name of webisites form database.
<fieldset>
<h1>A</h1>
<ul>
<?php foreach ($records as $key) { ?>
<li class="siteli"> <a href="#" class="add">
<div id="site-icon"><img src="<?php echo $key->site_img; ?>" width="16" height=""></div>
<p id="text-site"> <?php echo $key->site_name; ?></p>
</li>
<?php } ?>
</ul>
</fieldset>
Now I'm trying to group this results alphabetically by adding A, B, C etc as title.
Example,
A
Amazon
Aol
Aol Mail
B
Bing
Bogger
You can use array sorting to sort the array. In your case I would choose sort()
Now to show the links with a preceding Letter I would use:
<?php
$records = ['Aaaaa', 'Aaaa2', 'bbb', 'bbb2', 'Dddd'];
$lastChar = '';
sort($records, SORT_STRING | SORT_FLAG_CASE); //the flags are needed. Without the `Ddd` will come before `bbb`.
//Available from version 5.4. If you have an earlier version (4+) you can try natcasesort()
foreach($records as $val) {
$char = $val[0]; //first char
if ($char !== $lastChar) {
if ($lastChar !== '')
echo '<br>';
echo strtoupper($char).'<br>'; //print A / B / C etc
$lastChar = $char;
}
echo $val.'<br>';
}
?>
This will output something like
A
Aaaa2
Aaaaa
B
bbb
bbb2
D
Dddd
Notice that the C is missing, because there are no words starting with C.
This is a modification of #Hugo Delsing's answer.
I needed to be able to group my brands together like this, but one bug in the code was the fact that if I had say iForce Nutrition and Inner Armour it would group these into two separate groups because of the letter case.
Changes I Made
Because it was fully alphabetical, it was only going by first letter I changes SORT_STRING to SORT_NATURAL
Changed: if ($char !== $lastChar) to if (strtolower($char) !== strtolower($lastChar))
<?php
$records = ['FinaFlex', 'iForce Nutrition', 'Inner Armour', 'Dymatize', 'Ultimate Nutrition'];
$lastChar = '';
sort($records, SORT_NATURAL | SORT_FLAG_CASE); //Allows for a full comparison and will alphabetize correctly.
foreach($records as $val) {
$char = $val[0]; //first char
if (strtolower($char) !== strtolower($lastChar)) {
if ($lastChar !== '')
echo '<br>';
echo strtoupper($char).'<br>'; //print A / B / C etc
$lastChar = $char;
}
echo $val.'<br>';
}
?>
The final output will be like this
D
Dymatize
F
FinaFlex
I
iForce Nutrition
Inner Armour
U
Ultimate Nutrition
I hope this helps everyone, and a big thank you to Hugo for providing the code that got me exactly where I needed to be.
You can see my example here https://hyperionsupps.com/brand-index
$records = ['FinaFlex', 'iForce Nutrition', 'Inner Armour', 'Dymatize', 'Ultimate Nutrition'];
$temp=array();
$first_char="";
for($i=0;$i<count($records);$i++)
{
$first_char= strtoupper ($records[$i][0]);
if(!in_array($first_char, $temp))
{
echo strtoupper($first_char).'<br>'; //print A / B / C etc
}
$temp[]= $first_char;
echo $records[$i]."<br>";
}
I'm trying to put an image as a separator between menu items but not on the outside and I'm not sure how to do this.. So it would end up being something like this:
HOME | ABOUT | CONTACT
unfortunately my code puts one after every entry including the last one.
mysql_select_db($database_db_connection, $db_connection);
$query_rsMenu = "SELECT * FROM menu WHERE online = 1 ORDER BY position ASC";
$rsMenu = mysql_query($query_rsMenu, $db_connection) or die(mysql_error());
echo "<ul class='MenuBarVertical'>\n";
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
echo (" <li>" . $row_rsMenu['menuName'] . " <img src='SiteFiles/Site/separator.jpg' /> </li>\n");
}
echo "</ul>\n";
mysql_free_result($rsMenu);
Thanks
You could also build an array and use implode when you print it out. This also separates the database model from the view a little better.
mysql_select_db($database_db_connection, $db_connection);
$query_rsMenu = "SELECT * FROM menu WHERE online = 1 ORDER BY position ASC";
$rsMenu = mysql_query($query_rsMenu, $db_connection) or die(mysql_error());
$array = array();
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
$array[] = "<li>" . $row_rsMenu['menuName'] . "</li>\n";
}
mysql_free_result($rsMenu);
echo "<ul class='MenuBarVertical'>\n";
echo implode(' <img src="SiteFiles/Site/separator.jpg" /> ', $array);
echo "</ul>\n";
Of course the tags end up between the li instead of inside, but since you are making the li inline I think it will work.
The easy solution is to special case either the last iteration or the first one. The first one is usually easier: set $first = true outside the loop, inside the loop: if (!$first) { print 'separator'; }.
$count = 0;
$dbRows = mysql_num_rows($rsMenu);
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
$count++;
echo (" <li><a href=\"../" . $row_rsMenu['menuURL'] . "\">" . $row_rsMenu['menuName'];
if($count < $dbRows)
echo ("</a> <img src='SiteFiles/Site/separator.jpg' /> </li>\n");
}
You could use mysql_num_rows() to get the number of rows from the result set, and build some logic against the result.
Yet another answer :
for ($i = 1; $i <= mysql_num_rows($rsMenu); $i++) {
$row_rsMenu = mysql_fetch_assoc($rsMenu);
// do something;
if ($i == mysql_num_rows($rsMenu) - 1) {
// this is the last element, do something;
}
}