This is an old revision of the document!
Objective
In this activity you will create a form and use it to pass data from one page to another.
Setup
form.php
<?php
include('header.php');
include('menu.php');
?>
<main>
<p>Choose your hero.</p>
<ol>
<li><a href="process_form.php?name=Loki">Loki</a></li>
<li><a href="process_form.php?name=Hulk">Hulk</a></li>
</ol>
</main>
<?php
include('footer.php');
?>
process_form.php
<?php
include('header.php');
include('menu.php');
?>
<main>
<p>You have chosen <?php echo $_GET['name']; ?></p>
</main>
<?php
include('footer.php');
?>
Open 'form.php'. We will display our form here.
Add a new line below the opening <main>
tag.
Type 'form' and select the option that appears.
The
<form>
tag has a parameter called
action
. This is where you want to send your data.
Set action
to 'process_form.php'.
<form action="process_form.php"></form>
<button type="submit" name="name" value="Loki"></button>
<button type="submit" name="name" value="Hulk"></button>
Setting the type
to 'submit' means that when we click the button it will submit the form and send the data. Both buttons will do this.
name
is the parameter name to be sent. Submit buttons will often be named 'submit' and not contain data, but sometimes there will be two forms on a page (or sent to a page) and you need to know which one to process. We use that here to differentiate the selected heroes.
The value
is the text that will appear on the button.
Save and upload the file, then open the page.
Click on your chosen hero then check the results. Do you see your hero's name?
This is an unusual way to use a Submit button, but it's valid. Let's look at other options.
Text Input
Let's create a form to add heroes to our database.
We'll need input fields for the hero alias, (secret) identity, whether they're a hero or a villain, the year they first appeared in Marvel comics (or elsewhere) and what the source of their power is.
We could use a table to present our form with labels on the left and inputs on the right, but that isn't responsive, that is, it won't adapt to smaller screens.
Instead, we'll use a list, where each label / input pair is a list item.
Delete everything inside the
<form>
tag and add the following code.
<ul>
<li>
</li>
</ul>
<li>
<label>Hero Alias:</label>
<input type="text" name="alias" size="30" maxlength="50" hint="Iron Man">
</li>
<li>
<label>Identity:</label>
<input type="text" name="identity" size="30" maxlength="50" hint="Tony Stark">
</li>
Here we have a label for our input, using the
<label>
tag.
We then have an input, but rather than being of type="button"
or type="submit"
, it is type="text"
which is used for a simple text field, usually up to 100 characters or so.
We give it a name
that will inform 'process_form.php' what the value refers to.
There are two additional attributes that we haven't seen before. size
sets the size of the input box to 30 characters and maxlength
limits the length of characters that can be entered.
Finally, we have the option to give the user a hint as to what kind of content we expect here using hint
.
Save and upload the code to see how it looks live.
When we have an input with only a few set options and only one can be selected at a time, we use radio buttons.
The most common example of this is 'male' and 'female'.
In this case we want to know whether our hero is actually heroic or villainous. Add the following code to show this.
<li>
<label>Side:</label>
<input type="radio" name="side" value="Hero" checked="checked"> Hero<br>
<input type="radio" name="side" value="Villain"> Villain
</li>
I've labelled this hero/villain distinction 'side' but if you can think of a better term, feel free to use that.
Again, radio buttons use the
<input>
tag and, like buttons, they have a name and a value.
The value
isn't displayed as it is on a button, because there's no room on a radio button. Instead, the value is the text we want to send to 'process_form.php'.
We add the text before or after the <input
depending on how we want the form to appear.
Finally, notice the checked
attribute in the first input. This sets the default item if you want one.
Save and upload to see how it looks.
Number
Our next field is the year that the hero first appeared in a comic (or movie etc).
It will be sent as text, but it's actually a number and we can help our user by specifying that.
Add the following code to your form.
<li>
<label>First Appearance:</label>
<input type="number" name="year">
</li>
We can also set size
and maxlength
, but we'll look at better ways to manage this later.
Save and upload the code to see how it looks. Almost exactly the same a text input, right?
Notice that it has up and down arrows to allow users to change the number by increments.
If you have a mobile to load the page with, you'll also notice that the keyboard automatically changes to a numeric input rather than the usual keyboard layout.
Dropdown Boxes
Our next field is the source of the hero's power. This is a type of category, where we want to control the options that can be selected.
For this we use a
<select>
field.
Copy the following code into your form.
<li>
<label>Source of Power:</label>
<select name="power">
<option value="skill">Skill</option>
<option value="bio">Biological</option>
<option value="magic">Magic</option>
<option value="tech">Technology</option>
<option value="mutant">Mutant</option>
</select>
</li>
We have a number of options listed using
<option>
tags and they all sit inside the
<select>
tag.
Rather than setting the
name
for each option individually, we set it once in the
<select>
tag.
The value sent to 'process_form.php' is taken from the
value
attribute, while the user sees the text between the
<option>
tags.
Save and upload the file to see that it appears as a dropdown box.
Finally, add the submit button to make the form work.
<input type="submit" name="submit" value="Add Hero">
Save and upload the file.
Add some data and click on the button to submit your data.
Notice that if you choose 'Biological' as the source of power, the result is sent as 'power=bio' rather than 'power=Biological' because of the value
associated with that option.
Database Query
We'd also like to be able to add the appearances for each hero. This could be done a number of ways, but let's create a separate form for it.
Add a form below the existing one with the same action ('process_form.php').
Add an unordered list with two entries.
The first entry will have a label of 'Hero' and a select box with all our known heroes in it. Since we want it to update if we add heroes using the first form, we should pull the data from the database.
To do this, we'll need to set up our database first.
Add the following line before including the header.
include('database.php');
<?php
// Set up database connection
define ('DBCONNECT', "../../pdo.php"); // database connection
include DBCONNECT;
$db = 'webdev';
$dsn = "mysql:host=$db_host;dbname=$db;charset=utf8mb4";
try
{ // connect
$pdo = new MyPDO($dsn, $db_user, $db_pass, $db_options);
} catch (\PDOException $e) {
throw new \PDOException ($e->getMessage(), (int)$e->getCode());
}
?>
// get list of heroes
$query = "SELECT * FROM heroes";
$args = array();
$rslt = $pdo->prepare($query);
$rslt->execute($args);
<li>
<label>Hero</label>
<select name="hero">
<?php
// display list of heroes
while($row = $rslt->fetch()) {
?>
<option value="<?php echo $row['alias']; ?>"><?php echo $row['alias']; ?></option>
<?php
}
?>
</select>
</li>
Checkboxes
The second list item in this form will be the movies.
We'll need to get this list from the database too.
Add the following code underneath the hero query
// get list of movies
$query = "SELECT * FROM appearances";
$args = array();
$mrslt = $pdo->prepare($query);
$mrslt->execute($args);
<?php
// display list of movies
while($row = $mrslt->fetch()) {
?>
<li></li>
<?php
}
?>
You should recognise most of this code as it is the same as the code above with a few modifications. $hrslt
is now $mrslt
because we're looking at the movie query result rather than the hero query result.
Now, let's add the checkbox
<li><input type="checkbox" name="movie[]" value="<?php echo $row['movie']; ?>" id=""> <?php echo $row['movie']; ?></li>
Note that the checkbox input is very similar to a radio input. It has a name and a value and some text to be displayed.
The name is slightly different. The name 'movie' is appended by []
because we want to send a list of appearances as an array.
Upload the saved code and refresh the page.
You should see a list of movies with a checkbox in front.
Unfortunately, 'The Avengers' appears 5 times.
GROUP BY
To fix this, let's take a look directly at the database.
Open PHPMyAdmin and select the table 'appearances'.
The list of movies appears just as it did on our page, which says that our query worked correctly.
Our problem is that we really only want to see each movie once.
We can do that using 'GROUP BY' in our query.
Click on the 'SQL' tab and enter the following query.
SELECT * FROM `appearances` GROUP BY movie
You'll get an error saying that there is a 'nonagregated column' in our result. This means that some of the other data (in this case both id and the character_name can have different data for the same value of movie and MySQL doesn't know what to show.
Look at lines 4 and 5 to see this. When we group all heroes that appear in 'The Avengers' MySQL wants to squeeze the id (4 and 5) and the character_name (Captain America and Hulk) into the same row, but it can't.
There are some tricks we can do with numbers (like proving the total) and we could even get the first entry only, but for now we only really want the name of the movie, so let's specify that in the query.
SELECT movie FROM `appearances` GROUP BY movie
Run this query and see that we get a list of movies, each only appearing once. Perfect.
Now let's place this in our query in 'form.php'.
// get list of movies
$query = "SELECT * FROM appearances GROUP BY movie";
$args = array();
$mrslt = $pdo->prepare($query);
$mrslt->execute($args);
Add Movie
What will our user do when they want to add an appearance for a movie that isn't yet listed.
For example, Scarlet Witch is listed as a hero, but she doesn't appear in any of the movies in list.
We need a line where the user can add another movie.
Add this code after the loop (but before the
</ul>
tag).
<li><input type="checkbox" name="movie[]" value="new" id=""> <input type="text" name="new_movie"></li>
Multiple Parameters
Finally, we need our submit button before the closing
</form>
tag.
<input type="submit" name="submit" value="Add Appearance">
Refresh the page, enter some data and click submit.
Look at the
URL with all our data in it.
Notice that rather than using commas to separate out each name/value pair, pairs are separated by &
.
Also notice that when you send a field with two words, the space is replaced by +
symbol. This is why we started with just 'Hulk' and 'Thor' in the first activity.
Now that we have everything working, I think we can improve the styling a bit.
Next: Styling