I am contemplating taking the next step with my PHP applications and making the option fields dynamic. That would open the doors for more automation.
I have drop downs throughout my project, they are used to select a specific user and I update them manually when a new user is added (which is also a manual process). But if i take the first step and make these drop downs become populated by a MySQL Database, then i can move on to dynamic user creation.
I know how I can achieve this, but I am curious about some other alternatives (If there is any).
Here is what I would do..
$query = ** MySQL Select * From Database Query **
echo '<select name="usernames">';
while($row == mysql_fetch_array($query))
{
echo '<option>' . $row['username'] . '</option>';
}
echo '</select>';
So my questions is, would you do this differently? And why? Thanks!
What you are doing will work fine. I like to make it into a function so that if I ever need that dropdown on another page I dont have to write a lot of code over again.
function userDD()
{
$query = ** MySQL Select * From Database Query **
$html = '<select name="usernames">';
while($row == mysql_fetch_array($query))
{
$html .= '<option>' . $row['username'] . '</option>';
}
$html .= '</select>';
return $html;
}
This code does exactly what your code does except it doenst use echo. Instead you use a variable ($html) to store all of the data then when you are done you return it.
Your way is fine, but two things need to be changed:
- Run htmlentities() or htmlspecialchars() on all echoed HTML to avoid XSS. Unless you already sanitized it at database entry time but I find this practice silly.
- Add a value attribute to each <option> tag, otherwise you won't be able to retrieve the username selected. I suggest using the username's corresponding ID or something else that's unique to that user. If it's a string, use htmlentities/htmlspecialchars on it too.
php file
$users = getUsers();
include('template.tpl');
template
<select name="username">
<?php foreach( $users as $user ): ?>
<li><?= e( $user['username'] ) ?></li>
<?php endforeach; ?>
</select>
e is a function that escapes strings to prevent xss attacks
I wouldn't put an SQL query in the same document as my output...
I'd create a document containing all SQL queries, in functions, and include that file. Just to keep things seperated.
Related
I've got a search function written in PHP/MySQL which works fine. What I want to happen is that when a user produces a search they can click a button which will submit the $id from the output to a table in my database.
I've copied my code below, the error is within the php echo in the form, it just displays the plain text of the php code.
Everything else works fine, I've tested this by setting value to "" and entering the id myself and then it works. I want it though to be a hidden input in future where the id automatically comes through from the search result. Multiple searches can be returned on the same page and this form is underneath each individual search result.
<?php
$conn = mysqli_connect("localhost","root","","users");
$output = '';
if(isset($_POST['search'])) {
$search = $_POST['search'];
$search = preg_replace("#[^0-9a-z]i#","", $search);
$query = mysqli_query($conn, "SELECT * FROM users WHERE main LIKE '%".$search."%'") or die ("Could not search");
$count = mysqli_num_rows($query);
if($count == 0){
$output = "There was no search results!";
}else{
while ($row = mysqli_fetch_array($query)) {
$id = $row ['id'];
$main = $row ['main'];
$postcode = $row ['postcode'];
$available = $row ['available'];
$email = $row ['email'];
$output .='<div><br><b>Player ID: </b>'.$id.'<br><b>Main:
</b>'.$main.'<br><b>Postcode: </b>'.$postcode.'<br><b>Available:
</b>'.$available.'<br>
<br>
<form action="request_player.php" action="post">
<input type="text" name="id" value="<?php echo $id ?>">
<input type="submit" value="Request Player">
</form>
</div>';
}
}
}
echo $output;
?>
<br> Back to your account
The issue Jay Blanchard highlighted and which you took a bit lightly - perhaps b/c you fear the distraction from your current problem - is actually pretty related to the issue you highlight in your question.
This btw. is nothing uncommon. In this little script you deal with at three languages: HTML, SQL and PHP. And all these are intermixed. It can happen that things jumble.
There are methods to prevent these little mistakes. What Jay highlighted was about how to encode a SQL query correctly.
The other problem is to encode a HTML string correctly. Let me highlight the part:
$output = '... <input type="text" name="id" value="<?php echo $id ?>"> ...';
In this PHP string you write "<?php echo $id ?>" verbatim, that means, this will echo'ed out then.
What you most likely meant was to write it this way:
$output = '... <input type="text" name="id" value="' . $id . '"> ...';
So this seems easy to fix. However, it's important that whether it is SQL or HTML, you need to properly encode the values if you want to use them as SQL or HTML. In the HTML case, you must ensure that the ID is properly encoded as a HTML attribute value. In PHP there is a handy function for that:
$output = '... <input type="text" name="id" value="' . htmlspecialchars($id) . '"> ...';
Or as the ID is numeric:
$output = '... <input type="text" name="id" value="' . intval($id) . '"> ...';
works similarly well.
You need to treat all user-data, that is all input - which includes what you get back from the database (!) - needs to be treated when you pass it into a different language, be it HTML, SQL or Javascript.
For the SQL Jay has linked you a good resource, for the HTML I don't have a good one at hand but it requires your own thoughtfulness and the will to learn about what you do (write) there. So sharpen your senses and imagine for each operation what happens there and how this all belongs together.
One way to keep things more apart and therefore help to concentrate on the job is to first collect all the data you want to output and then process these variables in a template for the output. That would prevent you to create large strings only to echo them later. PHP echoes automatically and a benefit of PHP is that you can use it easily for templating.
Another way is to first process the form input - again into your own variable structure - which is the programs input part and run first. Then follows the processing of the input data, in your case running and processing the database query. And after that you care about the presentation. That way you have common steps you can become more fluent in.
I hope this is understandable. It's full of further obstacles, but it pays to divide and conquer these programming problems. It will also help you to write more while you need to write less for that.
And btw., you don't need to switch to PDO, you can stick with Mysqli.
The reason it is happening is because you have put <?php echo $id ?> inside a string. You want to do the same thing you did elsewhere in your example: value="' . $id . '" It can quickly get confusing when you have single and double quotes happening together. You might be best off learning how to use PHPs multiline strings.
Also, <?= $id ?> is a useful shorthand for <?php echo $id ?> (although you don't want to use either here)
I am a beginner trying to ouptut the values of dropdown menu from a database. I already automatically generate the values from database but the problem i am having is I want the the value that is being selected to be displayed.
Ideally im trying to update a Subject which I want to data to be displayed in an HTML page where each item could be updated. What i need is to be able to select the 'position' of the subject that is beeing selected.
Here is my code:
<p>Position:
<select name="position">
<?php
$sel_subject = get_all_subjects();
$subject_count = mysql_num_rows($sel_subject);
//$subject_count+1 because we are adding a subject
for($count=1; $count <= $subject_count+1; $count++) {
echo "<option value=\"{$count}\"";
if($sel_subject['position'] == $count) {
echo " selected='selected'";
}
echo ">{$count}</option>";
}
?>
</select>
You seem to be relying on $count to be some internal ID that remains static; given that it's just a monotonically advancing integer, this seems like a risky proposition. However, if you're comfortable with that, all you need to do is change the value in the last echo statement to be the subject name instead of $count. I would instead encourage you to use something meaningful to the database - for example, some people create an auto_increment field called subject_id and key off of that; others like to use UUIDs.
I would also generally suggest using a foreach loop instead of a for loop, as it tends to simplify the code (you don't have to worry about maintaining the counter, or creating fence post errors, etc.) Here's a brief example - I'm guessing a bit at what the actual data is that is available to you, hopefully you can extrapolate it to what you actually have.
<p>Position:
<select name="position">
<?php
$sel_subject = get_all_subjects();
foreach($sel_subject as $subject_num => $subject) {
echo '<option value="', $subject_num, '"';
if ($subject['selected']) {
echo 'selected="selected"';
}
echo '>', $subject['subject_name'], '</option>';
}
Thanks for taking time to look at this.
I have two drop down menus. The first is a list of clients, the second is a list of projects.
All projects are tied to just one client, so I'd like for the code to get user input for the client, then read that value, and modify the PHP code to only print out the values in the second drop down menu that correspond to the client selected.
Here's some code. For the first drop down menu:
<div class="item">
<label for='clSel' id='tsClLabel'>Client:</label>
<select name='clSel' id='wClient' onChange="bGroup();">
<option></option>
<?php
$cQuery = "SELECT * FROM Clients ORDER BY Client_Name";
$cResult = mysql_query($cQuery);
while($cData = mysql_fetch_assoc($cResult)) {
echo '<option id="Cid" value="'.$cData['Id'].'">'.$cData['Client_Name'].'</option>';
}
?>
</select>
Here's my jQuery function to get the user-selected value from the first drop down:
<script>
function bGroup(){
val1 = $("#wClient").val();
// window.alert(val1);
// $('#div1').html(val1);
return val1;
}
</script>
And the code for the second drop down menu:
<label for='billGroupId'>Billing Group: </label>
<select name='billGroupId'>
<option value=''></option>
<?php
$sql = "SELECT * FROM Billing_Groups ORDER BY Client_Id, Name";
$sth=$dbh->prepare($sql);
$sth->execute();
while ($row = $sth->fetch())
{
if ($row['Name']!= ''){
echo "<option value='".$row['Id']."' > ".$row['Name']."</option>";
echo "<script> bGroup(); </script>"
}
}
?>
</select>
I know I need to include a WHERE statement in the second drop down menu
Basically Select * FROM Clients WHERE Client_ID == $jsVAR.
I already have the value I need in the var1 JavaScript variable. How can I get this little piece of data either read by PHP or sent to PHP via JS code?
Thanks!!
You can SELECT all records from the database, and then insert them to your page HTML using json_encode(). Something like that:
<?php
$sql = "SELECT * FROM Billing_Groups ORDER BY Client_Id, Name";
$sth=$dbh->prepare($sql);
$sth->execute();
$projectData = array();
while ($row = $sth->fetch())
{
if ($row['Name']!= ''){
$projectData[$row['Client_Id']][] = $row;
}
}
echo '<script type="text/javascript">var projects=', json_encode($projectData), ';</script>';
?>
Then, in your JS, you use the variable projects as an associative array (object), eg.:
<script type="text/javascript">
for (p in projects[clientId]) {
alert(projects[p].Name);
}
</script>
Tricky one,
You have a choice. One way is to use Ajax to grab the second level menu structure upon getting the first level choice, and populate the second level once that succeeds. That's likely to be a problem, as there will likely be some sort of network delay while that happens, of which you have no control (unless you are in a closed environment). So from a user point of view it could be counter intuitive and sluggish feeling, especially on a slow connection or shared hosting solution where timings can vary enormously.
The other way is to somehow pull all values possible and filter them (so hide the ones that don't apply) using jQuery, perhaps utilising classes or some other attribute as a method of filtering data. Using jQuery you can assign data to elements so you could also use that too. The second method may not be so good if there's a lot of data (can't tell from the scenario you've described). Looking at your second level code I don't see a WHERE condition so I'm not sure how the value from the first level is affecting that of the second level, so it's hard to know how to deal with that for this method.
I am trying to dynamically build a drop down menu using PHP. The idea is: the elements are formed from a loop which calls and array. If the array element matches the data held in session then it adds the "selected" attribute to the tag, meaning that the page displays the previously selected option.
I have tried to include one complete set of code here, all the way from defining the variables from session data to echoing the HTML for the form element.
It doesn't currently work - the drop down menu appears, but is blank, and has no options. I've debugged it with ideone and it seemed to run successfully, and I can't see where I am going wrong, however this is my first PHP function! So I'm sure I've screwed it up somehow :)
Any help much appreciated.
<?php
session_start();
//if the session data has been set, then the variable $sv_02 is defined
//as the data held in the session under that name, otherwise it is blank
if (isset($_SESSION['sv_02'])) {$sv_02=$_SESSION['sv_02'];} else {$sv_02="";}
//define the array
$dm_sv_02 = array('-Year','-2012','-2011','-2010','-2009');
//create the function
function dropdown($dropdownoptions, $session_data)
{
foreach($dropdownoptions as $dropdownoption){
if($session_data == $dropdownoption){
echo '<option value="' . $dropdownoption . '" selected>' . $dropdownoption . '</option>';
} else {
echo '<option value="' . $dropdownoption . '">' . $dropdownoption . '</option>';
}
}
}
//echo the HTML needed to create a drop down, and populate it with
//the function which should create the <option> elements
echo '<select name="sv_02">';
dropdown($dm_sv_02, $sv_02);
echo '</select>';
?>
Try this:
foreach ($dropdownoptions as $dropdownoption) {
echo ($dropdownoption == $sv_02) ? "<option selected=\"selected\" value=\"$dropdownoption\">$dropdownoption</option>" : "<option value=\"$dropdownoption\">$dropdownoption</option>";}
This turned out to be a result of the fact I was using {smarty} tags to build my php, the code was as written but only worked when it was all included in one smarty tag, I'm not sure I understand why that should be the case but in any regard it was fixed by including it all in one tag.
Thank you so much for being so helpful. Owe you all a thank you. I will be asking more questions in the future. Someone has solved the problem by giving me this code:
echo "" . strval($row['style']) . "" . "";
and it worked beautifully!!!!!!!!! You rock!
I am sorry, I don't know how to post follow up questions, so I keep posting each question as a new question. I've never joined any forum before, so don't know how to follow a thread :( Sorry
I previously asked a question, but didn't post my code, so many kind people (thank you so much) who respanded couldn't help me out.
So I'll post my partial code below.
";
echo "Select an item";
echo "";
}
while($row = mysql_fetch_array($result))
{
echo "$row[style] $row[color]";
}
mysql_close($con);
echo "";
echo "";
echo "Enter your 4 digit postcode";
echo "";
echo "";
echo "Enter quantity";
echo "";
echo "";
echo "";
echo "";
?>
Then to process form, I use $_POST['item'] to find out which item was selected, I get the first word, the rest of the words are missing.
For example, if the dropdown box was populated with the follwoing:
Dressmaker mannequin size 12
Mannequin torso PH-9 in skin color
...
if item selected was "Dressmaker manenquin size 12", $_POST['item'] gives me Dressmaker, the rests are missing.
I spent whole last night and today searching, but have made no progress, please help :(
This still applies from my previous post:
//====== Begin previous post
Hopefully, your MYSQL database has a primary key? If it does, set the value of each <option> to the primary key of the item.
For example:
SQL
id desc
1 "dressmaker thing with mannequin"
2 "dressmaker thing no mannequin"
Form PHP
echo "<option value='".$query['id']."'>".$query['desc']."</option>";
When the form is submitted, re-query the database for the desired description. You'll be doing this re-query anyway to retrieve prices and such, yes?
The reason this is happening is that spaces are discouraged in HTML attributes. You shouldn't have an attribute like value='this attribute is spaced'.
//====== End previous post
Basically, change this line:
while($row = mysql_fetch_array($result))
{
echo "<option value=$row[style]>$row[style] $row[color]</option><br />";
}
to
while($row = mysql_fetch_array($result))
{
echo "<option value='".$row['id']."'>$row['style'] $row['color']</option><br />";
}
and add this in process_form.php to get the description:
$desc = mysql_query("SELECT style FROM products WHERE id='".$_POST['item']."';");
You can also use this to get all other related info from the DB right when you need it.
// Another edit
#Cambraca - right on - I forgot to sanitize the quote.
#Ottoman - Your solution is a temporary fix. I strongly recommend applying an id/primary key system if it's not in place. An ounce of prevention is worth a pound of cure.
That is because in php you get what is in the "value" attribute of the dropdown's options.
You need to do something like this:
Replace
echo "<option value=$row[style]>$row[style] $row[color]</option><br />";
with
echo "<option value=\"$row[style] $row[color]\">$row[style] $row[color]</option><br />";
The problem is your lack of quotes in the option "echo" statement.
Try something like this
while($row = mysql_fetch_array($result))
{
printf('<option value="%s">%s %s</option>',
htmlspecialchars($row['style']),
htmlspecialchars($row['style']),
htmlspecialchars($row['color']));
}
Note also, the <br> element does not belong in the <select>
Edit: Added htmlspecialchars to properly escape any HTML entities that might exist in retrieved strings
If it gives you only the first word, then you forgot to enclose the option value="with quotes". Otherwise show us the constructed HTML source.