Web development #5: User input with HTML Forms

In my last blog post we’ve seen how to create dynamic web pages using PHP. The examples in this post are using the code examples from that blog post, so if you haven’t read it I suggest you do. You can find my other posts here:

  1. Web development #1: Internet and the World Wide Web
  2. Web development #2: Our first website using HTML
  3. Web development #3: Styling our page with CSS 3
  4. Web development #4: PHP in the back
  5. Web development #5: User input with HTML Forms
  6. Web development #6: Getting interactive with JavaScript
  7. Web development #7: Dynamic page updates with AJAX
  8. Web development #8: Where to go from here

In the last post we created a page that would show movies (or music, or whatever) based on a simple text file (because I’m not covering databases). You could simply add new lines to the text file and they would show on your page (after a refresh). But now you probably want to add new lines directly from your website and not in the file. Why would you want that? Well, for example, because your users don’t have access to your file (and rightfully so)! Also because your web interface is more user friendly than direct file access. When you’re going to implement an actual website you’ll probably be using an actual database and you’ll be working with more data than just lines in a file. You may want to ask users for their name, address, gender, password, for webshops you want to know their preferred shipping and payment methods. And of course you want users to add content to your site, like blogs, product reviews, messages, etc. There’s plenty of cases where you’d want user input!

So we have basically two options: HTML Forms or AJAX calls. AJAX calls are discussed in a later blog post, so in this one I’m going to focus on HTML Forms.

What are forms?

Forms are actually just a couple of HTML tags! <form></form> with some input tags, <input /> of which one has the type submit, <input type=”submit” />. Sounds easy, right? After all, you want your users to fill out a (digital) form where they give their input and then submit it to the server. How does this look?

<form action="MySite.php">
    <input type="text" name="name" />
    <input type="submit" />
</form>

Is it that easy? Almost! There are quite a few input types, such as checkboxes, radio buttons, date pickers and file pickers. We’ll look at some of them a bit later in this post. First let’s see what happens in the above HTML.

Save the above code in a file called MySite.php in your xampp htdocs folder. Now if you’d view this page you would see a field for the user to add text and a button saying “Submit” (it actually says “Verzenden” on my browser, which is the Dutch translation for “Submit”). Now what happens when you type in your name and click the submit button? You’ll be redirected to the site localhost/MySite.php?name=Your+name, which simply shows the same page again (because it was specified in the action attribute), but with your input emptied. You may not have noticed, but the entire page refreshed when you hit submit. The part behind the questionmark was added by the form and it contains the names and values of the input tags you have in your form tags. Now here’s the deal. You can actually get these values from your PHP code!

Now change your code to the following:

<?php
    if (isset($_REQUEST['name']))
    {
        echo $_REQUEST['name'];
    }
?>
<form action="MySite.php">
    <input type="text" name="name" />
    <input type="submit" />
</form>

Now what happens when you fill out your name and hit submit? Your name is being printed at the top of the page. But what’s happening in the code? Well, notice the isset($_REQUEST[‘name’])? PHP has some ‘superglobal’ variables. They’re variables that are visible in all your PHP code. $_REQUEST is one of them and it’s an array that contains any parameters that are send to your page. In this case we’re checking if the ‘name’ item was set. If it isn’t (when you first load the page) it does nothing. When it is (after a submit) we echo the value of ‘name’.

Notice that the action attribute of the form element indicates what page to navigate to. In this example I’m navigating to the page we’re already on, but it could’ve been any page. For example, try the following:

<form action="http://www.google.com/search">
    <input type="text" name="q" />
    <input type="submit" />
</form>

This will successfully open Google and search for your requested search term (Google uses ‘q’ for their parameter name).

GET and POST

So that’s the short version of it. The next thing you need to know is that in the previous examples we used the HTTP method GET to retreive our pages. Perhaps you remember from the first article in this series that GET is used to request a file from the server. In this case we requested the current page with parameter ‘name’ and we requested Google/search with parameter ‘q’.

Now what if we wanted to store information? We could use GET, sure. After all we simply send some data to our server where PHP can do with it what we want, right? All true, but that’s not always what we want. Suppose you want to save someone’s contact details. Would it look good in this huge URL http://www.mysite.com?name=sander+rossel&country=netherlands&address=…? No, it wouldn’t. Besides, your URL has a max length, so it won’t always work either.
Second, there is some data that you don’t want to send twice. What if someone was about to pay and they hit the refresh button (or even the back button)? Navigating to yourpage.com?payment=… would simply handle the payment again!
Last, there are some safety issues with GET. URL’s are stored in your browser history and on the server in plain text. Imagine sending your password like that! http://www.mysite.com?password=123456. Right, so is there another way? Yes, there is!

Whenever you want to send data to your server for storage, or data that is a bit more sensitive we can use the HTTP POST method. Let’s look at our first example again.

<?php
    if (isset($_REQUEST['name']))
    {
        echo $_REQUEST['name'];
    }
?>
<form action="MySite.php" method="POST">
    <input type="text" name="name" />
    <input type="submit" />
</form>

Wow, all I did was add the method attribute to my form element and assigned it the value of POST (method is GET by default). Now if you run this you’ll see your name on top of the page again (after a submit), but your URL will simply be MyPage.php. And try refreshing the page, your browser will warn you that information might be re-submitted.

PHP has specific superglobal variables for handling GET and POST variables specifically. They’re $_GET and $_POST, so you can use them instead of $_REQUEST (which has both GET and/or POST variables).

Other input

So we can now send some text input to the server. Surely you want more than that! Let’s look at some other input types. We’ll also tidy up our form a bit by using the label element.

<form action="MySite.php" method="POST">
    <label for="name">Name</label>
    <input type="text" name="name" id="name" required /><br><br>
 
    <label for="male">Male</label>
    <input type="radio" name="gender" id="male" value="male" checked /><br>
    <label for="female">Female</label>
    <input type="radio" name="gender" id="female" value="female" /><br><br>
 
    <label for="email">Email</label>
    <input type="email" name="email" id="email" /><br>
 
    <label>Receive newsletter
        <input type="checkbox" name="receiveNewsletter" checked /><br><br>
    </label>
 
    <label>Date of birth
        <input type="date" name="dateOfBirth" /><br><br>
    </label>
 
    <label for="avatar">Avatar</label>
    <input type="file" name="avatar" id="avatar" accept="image/*" /><br><br>
 
    <input type="submit" />
</form>

So that’s quite something. First, notice the <label> tags. I’m using them in two different ways. The first is to just declare them and associate them to an input field by specifying the for attribute and giving it the value of the id of the input I want to associate it with. The second way is by wrapping the input tags inside the label tags. Both ways are fine. Now if you click on a label the input gets focus or is selected/unselected. Nice!

Now for the different input types. We’ve seen the text type, so I’ll skip that one. I did add the required attribute though. Try submitting your form without filling out your name. There are more attributes like this one like max, maxlength, min and pattern.

Next is the password type. It looks very much like the text type, but if you type in it you get to see password characters rather than text.

Then comes the radio type. Notice I have two radio types, male and female. Also notice they have the same name. That means that if a radiobutton with a certain name is selected all other radiobuttons with the same name are unselected. In this case that means we can pick either male or female, but not both. I’ve also used the checked attribute for the male input. You don’t have to specify a value for checked. It will simply make this radiobutton checked. You could specify checked for both male and female, but your browser is only going to select one. It also makes for invalid HTML, so just don’t do that.

Following we see the email type. Again, looks like the text type, but if you commit your form your browser will check if the email address has valid syntax. That’s great, but don’t forget to check on the server too! Email is new in HTML 5 and will behave like text on older browsers.

Moving on we see the checkbox type. Not much to say, except that you can specify checked to have it checked, or omit it to have it unchecked.

Next is the date type. The user can pick or enter a date. The browser will validate if it’s a valid date (no 32st januari, etc.). This one is new in HTML 5 too and will also behave like text on older browsers.

Last, but not least, is the file type. You can use this to have a user select one or more files (if you need more than one simply add the multiple attribute, much like checked).

And of course you can handle all of those in your PHP code too. But I’m sure you can figure that out. There are other input types too, but I’ll leave it up to you to check them out. Just Google for HTML input.

Completing our example

So at this point we want to make our favourite movies example from my following blog work. Actually all we want to do is POST a movie title, add it to our text file and display it on our page. There’s actually a bit more to it than you might think… Here’s the complete code for the page.

<?php
    if (isset($_POST['movieName']))
    {
        $movieName = $_POST['movieName'];
        if ($movieName)
        {
            file_put_contents('movies.txt', htmlspecialchars($movieName) . "\r\n", FILE_APPEND);
        }
 
        header('Location: ' . htmlspecialchars($_SERVER['REQUEST_URI']));
        exit();
    }
?>
<!DOCTYPE html>
<html>
    <?php
        function fileAsUnorderedList($fileName, $notFoundMessage)
        {
            if (file_exists($fileName))
            {
                echo "<ul>";
                $lines = file($fileName);
                foreach ($lines as $line)
                {
                    echo '<li>' . htmlspecialchars($line) . '</li>';
                }
                echo "</ul>";
            }
            else
            {
                echo $notFoundMessage;
            }
        }
    ?>
    <header>
        <title>My favourite movies!</title>
        <meta charset="utf-8">
        <meta name="description" content="A list of my favourite movies.">
        <meta name="keywords" content="Favourite,movies">
        <meta name="author" content="Sander Rossel">
    </header>
    <body>
        <h1>My favourite movies!</h1>
        <p>
        <?php
            fileAsUnorderedList('movies.txt', 'No favourite movies found!');
        ?>
        </p>
        <h2>Add a movie!</h2>
        <?php echo '<form action="' . htmlspecialchars($_SERVER['REQUEST_URI']) . '" method="POST">' ?>
            <label for="movieName">Movie name</label>
            <input type="text" name="movieName" id="movieName" />
            <input type="submit" />
        </form>
    </body>
</html>

So that’s quite a lot! No worries. First of all you should notice that I’m handling our POST input. If movieName is set and it has a value (it’s truthy) we append it to our text file, followed by a new line (\r\n, or “line feed, carriage return” from ye olden days when we used typewriters).
What happens next is that we redirect to the current page using $_SERVER[‘REQUEST_URI’], another superglobal variable in PHP. So once we submit form data we get to our page with POST data. We handle the POST data and again load our page, but this time without POST data (a GET). If we wouldn’t do this we’d get an annoying pop-up every time we wanted to refresh our page. This technique is called the Post/Redirect/Get Design Pattern.

But there’s more happening. I’m using a function called htmlspecialchars, what’s that all about? Well, here’s a little practice for you. Remove all the htmlspecialchars from the code and add the following movie “<script>alert(‘hacked!’);</script>“. Now if you refresh the page you’ll get a popup saying “hacked!”. Quite annoying isn’t it? See it this way, people are going to submit text to your page and you’re going to echo that text as-is. But that text may be/contain valid HTML (and script)! And that would mess up your page or worse! It’s a huge security risk also known as Cross-Site Scripting or XSS. Now put the htmlspecialchars back in place and your page will simply display a movie with a rather weird name. So that’s what htmlspecialchars does. It makes sure your text is transformed into non-HTML, so > would be  echoed as &gt; etc. I’ve used this trick in a few places.

In our form elements I’m using the same tricks. I use $_SERVER[‘REQUEST_URI’] and htmlspecialchars. Why the $_SERVER[‘REQUEST_URI’]? If the name of your PHP file changes so would the URL to access it. If the URL was hard coded you’d have to check your PHP file and change all references to ‘movie.php’ to ‘myNewFileName.php’. With this trick we’ve got that covered!

A last remark on the PHP above the !DOCTYPE tag. Is this bad? Nope. Remember that all this PHP code is executed on the server and that your HTML is sent back. So by the time this file reaches your browser it has no knowledge of any code above !DOCTYPE.

Other than that you should know all the other stuff I’ve put in there. So now you have a website that actually takes user input, stores it on the server and serves that data back to the user. In the next blog we’re going to take a look at JavaScript, or code that runs from the browser! Good stuff.

Stay tuned!

Web development #4: PHP in the back

Missed me? It’s been a while since I last blogged (about three months). I’ve been busy moving to my own house and getting up-to-speed at a new job. Lots of good stuff, but no blogging. Well today is the day I’m picking this up again and I’m just going to act like it’s three months ago and continue with the series.

  1. Web development #1: Internet and the World Wide Web
  2. Web development #2: Our first website using HTML
  3. Web development #3: Styling our page with CSS 3
  4. Web development #4: PHP in the back
  5. Web development #5: User input with HTML Forms
  6. Web development #6: Getting interactive with JavaScript
  7. Web development #7: Dynamic page updates with AJAX
  8. Web development #8: Where to go from here

So in the previous installments we’ve created a web page using HTML and CSS. We can actually build pretty nice websites using just those, but we still run into some trouble. What if we wanted to add content to our site? We’d have to edit our HTML each time. What if we wanted to display our website in multiple languages? What if we wanted users to be able to add content to the site (such as a blog)? In other words, we want our content to be dynamic. That’s all not possible using just HTML and CSS. We’re going to need a bit more. We’re going to need something creating our HTML on the back-end.

For this blog post I assume you are familiar with HTML and CSS, which you can read about in my previous blog posts, and that you’ve worked with some programming language before, preferably some C-based language such as C# or Java.

Introduction to PHP

So our back-end is just a server listening for requests. Whenever a request comes in we want to handle it and send a response (such as an HTML web page). We can handle these requests with a variety of tools and languages, but for this article I’m using PHP.

Why PHP? First of all it’s free. Second, it’s one of the most popular web languages that has been around for a good long while. It has a huge community and lots of documentation and tutorials. Third, virtually all web hosts, even the free ones, have support for PHP. Other languages, such as C#, are not always supported. Last, but not least, PHP is quite easy to learn because it can be pretty lightweight. Actually I’m simply going to write my PHP in Notepad++.

So PHP was created twenty years ago, in 1995, by Rasmus Lerdorf. Back then the PHP stood for Personal Home Page. They changed it to PHP: Hypertext Preprocessor, making it a recursive acronym (because the first P stands for PHP, of which the first P stands for PHP, of which the first P…). Clever, huh? Anyway, PHP is a scripting language, meaning it is interpreted rather than compiled. It’s also procedural, object oriented, weakly typed and it has C-based syntax. Enough talking, let’s code!

Setting up your environment

Unfortunately we can’t code just yet. Remember that your browser renders HTML and CSS. It can also run JavaScript (which I will discuss in another blog post), but it can’t execute PHP files. Usually your server handles PHP execution. Chances are you don’t have a web server laying around. Luckily you can configure your own PC to act as a web server.

To do this simply install web server software. You have a few choices, but I’m going for XAMPP. You can download XAMPP here and then simply install it (choose all default options, or change them if you know what you’re doing). When the installation is done XAMPP will ask you to start the XAMPP Control Panel. Start it and you’ll see a list of options. We’ll need Apache, so just start it. Now start your favourite browser and navigate to http://localhost. You should see a XAMPP page. Congratulations, you have just installed a (local) web server and you can now run PHP files!

To check if it really works create a new text file and name it “hello.php”. Inside the file place the following text:

<?php
    echo "Hello, PHP!";
?>

Now go to the installation folder of XAMPP (you can go there quickly by using the ‘Explorer’ button in the XAMPP Control Panel), find the htdocs folder and place your hello.php file there. Now, in your browser, navigate to http://localhost/hello.php. You should see the text “Hello, PHP!” And now that we’ve got the mandatory Hello world example out of the way let’s start writing some real PHP.

Learning the syntax

So let’s first look at some basic PHP syntax. Basically you’re going to write an HTML page with some PHP in it. The PHP is going to create some text representing more HTML. To indicate that you’re going to use PHP use the <?php open tag and to indicate that you’re done with PHP use the ?> closing tag. You’ve seen this in the example earlier.

The echo, or alternatively the print, statement outputs your code to HTML. In the above example it creates the HTML “Hello, PHP!”, which is just some text. But we could make that echo “<h1>Hello, PHP!</h1>” and we would get a header on our page.

So as I mentioned PHP is weakly, or loosely, typed. That doesn’t mean PHP doesn’t have types, it means a variable can change its type while the code executes. It also means you can add 3 to “3” and the result might be 6 or “33”, so a bit of caution is required when working with weakly typed languages (and in fact PHP always converts text to numeric when adding).
So what are the types in PHP? First we have the int for numerics without fractional components (so 1, 8, 42 and 986 are valid integers, 1.12 is not). Second there is float, or double, for numerics with fractional components. Then we’ve got the boolean or bool for a simple true or false. Next is the string for text (or an array of characters). Then we’ve got the array, or a 0-based indexed collection of stuff. There’s the object type, which encapsulates state and behaviour. And last, and actually pretty literal least, there’s NULL indicating the absence of any value.
Nothing special if you’ve worked with other languages before.

So how do we go about and use these types? Usually we’d want to store them in variables. So how do we declare variables? We actually don’t… Just assign a value to some variable and all of a sudden it’ll be there. It’s a kind of magic! And a variable always start with the $ sign. The typical variable declaration then looks like this:

$intVar = 42;
$floatVar = 3.142;
$boolVar = true;
$stringVar = "Some string"; // Double quotes.
$stringVarAltern = 'Alternative string'; // Single quotes.
$arrayVar = array('Pulp Fiction', 'Fight Club', 'Star Wars');

class person
{
    public $name = NULL;
    public $age = NULL;
}

$objectVar = new person();
$objectVar->name = 'Sander';
$objectVar->age = 27;

$nullVar = NULL;

Now aside from the class and objectVar that looks pretty straightforward right? But beware, the following is completely legal (PHP is weakly typed, remember?):

$stringVar = 'Some string';
$stringVar = 42;

Now that’s something you do want to look out for.
There’s something else about strings too. See how you can declare a string using single or double quotes? Well, the double quote strings are interpreted strings, meaning that any variable name you place in there will be evaluated before the string prints. If you ever need to concatenate string you can use the . operator.

$hello = 'Hello';
echo '$hello world!'; // Outputs $hello world!
echo "$hello world!"; // Outputs Hello world!
echo "$helloish world!"; // Error, $helloish is undefined!
echo "{$hello}ish world!"; // Outputs Helloish world!
echo 'Conc' . 'aten' . 'ate!'; // Outputs Concatenate!

Another thing that might surprise you is that PHP can treat anything as a boolean! Any non-default value will be true while all default values will be false, also called truthy and falsey. The next example uses an if/else statement to illustrate this. Try playing around with it.

if ("Hello") // Try 0, '', '0', 0.1, NULL and array().
{
    echo "Yep...";
}
else
{
    echo "Nope!";
}

So I’ve also shown you an if/else statement. Let’s look at some loops too.

$movies = array('Pulp Fiction', 'Fight Club', 'Star Wars');

for ($i = 0; $i < count($movies); $i++)
{
    echo "$movies[$i] <br>";
}

foreach ($movies as $movie)
{
    echo "$movie <br>";
}

Now there’s actually quite something going on there! First we initialize an array, which we’ve seen before. Now in the first for loop we start by declaring our counter variable $i, then we do a boolean test to check if we need to loop once more and finally we do an update (increment $i) after each iteration. In the boolean check we also use the count(array) function to check if we still have more elements in the array. Ideally you would perform this count outside of the statement so it only gets performed once.
The second loop is a bit more readable. I’m basically saying “for each element, which I will call $movie, in the array $movies do this…”. Now in the loop’s body you can freely use the current element using the $movie variable.
There are also do– and while loops, but I won’t discuss them here. For a programmer this shouldn’t be anything new!

Writing a page

Now let’s write an entire page. Usually you’d have a database, such as MySQL, running, but that’s a bit overkill for this post. So we’re going to read lines of text from a text file and show them on the page. You’ll see that you can update your page without actually modifying your HTML or PHP file.

So let’s first take the example with my favourite movies. We’re going to put our favourite movies in a text file and print them on our page. So create a new PHP file, call it movies.php and put it in the hpdocs folder (which is in your XAMPP folder). Now create a text file called movies.txt and put it in your htdocs folder with your PHP file. You can put some movie names in your text file. Each name goes on a seperate line (I’m calling it movies, but any value would suffice, of course).

For this example I’m going to use an unordered list. I haven’t shown this yet, but the HTML is as follows:

<ul> <!-- Unordered List -->
    <li>Some item</li> <!-- List item -->
    <li>Another item</li>
    <li>Third item</li>
    <li>etc...</li>
</ul>

You could also use an ordered list, in which case you’d use <ol> tags instead of <ul> tags.

So your PHP file could look like this (excluding the !DOCTYPE, html, header and body tags):

<h1>My favourite movies!</h1>
<p>
    <?php
        if (file_exists('movies.txt'))
        {
            echo '<ul>';
            $lines = file('movies.txt');
            foreach ($lines as $line)
            {
                echo "<li>$line</li>";
            }
            echo '</ul>';
        }
        else
        {
            echo 'No favourite movies found!';
        }
    ?>
</p>

So using the PHP function file_exists(string) we’re first checking if the movies.txt file exists at all. If it doesn’t we’ll simply show “No favourite movies found!”, but if it does we’re going to create an unordered list and read the files contents using the file(string) function. The file(string) function reads all lines of a file and puts them in an array. There’s more functions for file manipulation, but I won’t discuss them here. Next we’re looping through the lines we just got from the file. For each line we’re appending a list item element to our HTML. When all the lines are processed we close our unordered list.
And that’s our page! You can view it by navigating to http://localhost/movies.php. You can use some CSS to make it look a bit prettier and you’ll probably want to add some content too.

Now imagine you’d get that out of a database? Pretty neat, huh!

Functions

Now there are times when you have certain code that you want to reuse. Let’s say we want to create another unordered list based on another file. The same rules apply, except maybe we don’t have movies, but songs that we’d like to display. We can create function for this and have the filename passed in as a parameter. So let’s look at how we can put the code above in a function. At the top of your page put the following:

<?php
    function fileAsUnorderedList($fileName, $notFoundMessage)
    {
        if (file_exists($fileName))
        {
            echo "<ul>";
            $lines = file($fileName);
            foreach ($lines as $line)
            {
                 echo "<li>$line</li>";
            }
            echo "</ul>";
        }
        else
        {
            echo $notFoundMessage;
        }
    }
?>

As you can see we’ve defined a function that does the same as our previous code, except the filename and the message when the file is not found are passed in as parameters. Now how can we call this?

<h1>My favourite movies!</h1>
<p>
    <?php
        fileAsUnorderedList('movies.txt', 'No favourite movies found!');
    ?>
</p>
<h1>My favourite music!</h1>
<p>
    <?php
        fileAsUnorderedList('music.txt', 'No favourite music found!');
    ?>
</p>

And look at that! You can now add a second text file to your htdocs folder and your favourite music will be displayed the same as your movies. You still see almost identical code here, so we could change our function and make it do a bit more or we could create a second function that creates the header and paragraph for us.

And what if you wanted to use this function on other pages? Simply put the function in a seperate file and include the following line of code in the PHP file where you want to use the function.

<?php include("MyFunctions.php"); ?>

If you want to further organize your code, and you’ll want that, you’ll have to use objects and namespaces. You’ve already seen a little example of an object earlier and I’m leaving it at that. Be careful with putting functions directly in your files though. What if two files you want to include contain the same functions (or variables)!? You’d have a problem. Using objects and namespaces help toward preventing this.

So that was a very short introduction to PHP. Probably shorter than it deserves. PHP has lots of functions, libraries, third party tooling and a large and active community. If you want to learn more about PHP I suggest you start by Googling for tutorials or perhaps read a book about it. For now you’ve created your first website with dynamic content using a server-side language though! In my next post (which won’t take me another three months) we’ll look at sending data from our website to the server so we can use our page to add movies or music to the text files.

Stay tuned!