Resources:

Form Syntax

edit

A web pages represents the interface of our web application and the backend scripts (e.g. PHP) implements the application logic. We must collect user input from the interface and send them to the application logic. HTML input controls are elements that collect user input and the form element can be used to send the data to the backend. Later we will learn how to submit the input programmatically using JavaScript.

Common input controls include text field, text area, drop-down list (select), checkbox, radio button, reset button, and submit button. Detailed usage and examples can be found in the following list:

Example

edit

Lets add add and delete functions to our todo list web application. Recall that we use a text file to store todo items with each item on a separate line. To add a new todo item to the list we must collect the new item as a user input, send it to a script on the server, and append the new item to our existing list of todo items.

Add TODOs

edit

We can use a add.php output an HTML form and ask it to submit user input in the form to add_submit.php.

<!--add.php-->
<form action="add_submit.php">
  <label>TODO:<input type="text" name="todo"/></label>
  <input type="submit" name="send" value="Add"/>
</form>

In the following add_submit.php script we get the value for the parameter (todo) and append it to the text file if the parameter is sent and has non-space characters in it. At the end of the list we include the list.php to output the current todo list as a feedback to the user. Note that once a user submit a new todo item the response will be displayed on a another page (add_submit.php), which doesn't include the form. If the user wants to continue adding new todo items, she will need to click on the back button, which in inconvenient.

# add_submit.php
<?php
  $todo = $_GET["todo"];
 
  if (isset($todo) && strlen(trim($todo)) != 0){
    file_put_contents("todolist.txt", $todo."\n", FILE_APPEND);
  }
  include "list.php";
?>
<ul>
<?php
  # list.php
  $todos = file("todolist.txt", FILE_IGNORE_NEW_LINES);
  $count = count($todos);
  for ($i=0; $i<$count; $i++){
?>
    <li><?=$todos[$i]?></li>
<?php
  }
?>
</ul>

In fact we could combine the two scripts into one so that users will see the add form and the current list all the time and be able to add new todo items. We will rename our script to todo.php.

<form action="todo.php">
  <label>TODO:<input type="text" name="todo"/></label>
  <input type="submit" name="send" value="Add"/>
</form>
<?php
  $todo = $_GET["todo"];
  
  if (isset($todo) && strlen(trim($todo)) != 0){
    file_put_contents("todolist.txt", $todo."\n", FILE_APPEND);
  }

  include "list.php";
?>

Note that the "\n" appended to each new line is important because we want each todo item in its separate line in the todolist.txt file. When requested this script will always output the add form and the current list (via list.php). If a parameter named "todo" is sent and it is not empty the value of the parameter will get appended to the todolist.txt file. A screen shot of the page generated by todo.php is as follows:

 

Delete TODOs

edit

In this next step we will allow users to delete individual todo items in the list. We need to modify the user interface (web page) for users to trigger the delete actions. When a link is click on a page the browser sends a request to a resource on the server identified by the action URL. We could add a delete link after each todo item and use it to trigger the deletion of the item. We will also need to create a script on the server to respond to such requests. The script needs to know which todo item a user wants to delete. Somehow each request needs to be specific to each item. We learned previously that we can append a query string to the URL of a request to parameterize it. The question now is what the parameter should look like. As each todo item is stored in the todolist.txt file as a line of text we can delete any todo item by deleting its line in the text file if we know the line number. The following script tests the idea of deleting a line by its line number. The line number is hardcoded, but eventually we want to get it as a parameter sent from a browser. The usage of the functions used can be found in the list following the code.

<?php
  $line_number = 6;
  if (isset($line_number)){
    $lines = file("todolist.txt");
    array_splice($lines, $line_number, 1);
    file_put_contents("todolist.txt", implode("",$lines));
}
?>

On the client side (in the HTML file) we can use URLs of the following format to send the line number. The name of the parameter "line_number" and value will be the actual line number for a particular todo item.

http://host/path/to/delete.php?line_number=3

We will need to revise the list.php file to output the delete links.

   <ul>
      <?php
        $todos = file("todolist.txt", FILE_IGNORE_NEW_LINES);
        $count = count($todos);
        for ($i=0; $i<$count; $i++){
      ?>
          <li>
            <?=$todos[$i]?>
            [<a href="delete.php?line_number=<?=$i?>">delete</a>]
          </li>
      <?php
        }
      ?>
    </ul>

The modified web interface should look as follows:

  The HTML source code looks as follows:

<form action="todo.php">
  <label>TODO:<input type="text" name="todo"/></label>
  <input type="submit" name="send" value="Add"/>
</form>
    <ul>
          <li>
            Buy milk            [<a href="delete.php?line_number=0">delete</a>]
          </li>
          <li>
            Buy eggs            [<a href="delete.php?line_number=1">delete</a>]
          </li>
          <li>
            Go for a run            [<a href="delete.php?line_number=2">delete</a>]
          </li>
          <li>
            Read a book            [<a href="delete.php?line_number=3">delete</a>]
          </li>
          <li>
            Teach a class            [<a href="delete.php?line_number=4">delete</a>]
          </li>
          <li>
            readsleepsleep            [<a href="delete.php?line_number=5">delete</a>]
          </li>
          <li>
            two            [<a href="delete.php?line_number=6">delete</a>]
          </li>
          </ul>

As you can see the values of the "line_number" parameters corresponds to the actual line numbers of the items in the todolist.txt file. Now whenever a delete link is clicked on the delete.php script will receive a request with a line_number parameter. We can now modify our delete.php script to handle such delete requests.

<?php
  $line_number = $_GET["line_number"];
  $lines = file("todolist.txt");
  array_splice($lines, $line_number, 1);
  file_put_contents("todolist.txt", implode("",$lines));

Note that the delete links points to a file different from todo.php (outputs our main page) causing browser to land on the empty delete.php page because it outputs nothing.

One Page Application

edit

It would be nice if we can stay on the same page (todo.php). The following code shows the whole application in one script:

<form action="todo.php">
  <label>TODO:<input type="text" name="todo"/></label>
  <input type="submit" name="send" value="Add"/>
</form>
<?php
  $todo = $_GET["todo"];

  if (isset($todo) && strlen(trim($todo)) != 0){
    file_put_contents("todolist.txt", $todo."\n", FILE_APPEND);
  }

  $line_number = $_GET["line_number"];
  if (isset($line_number)){
    $lines = file("todolist.txt");
    array_splice($lines, $line_number, 1);
    file_put_contents("todolist.txt", implode("",$lines));
  }
?>
<ul>
<?php
  $todos = file("todolist.txt", FILE_IGNORE_NEW_LINES);
  $count = count($todos);
  for ($i=0; $i<$count; $i++){
?>
  <li>
    <?=$todos[$i]?>
    [<a href="todo.php?line_number=<?=$i?>">delete</a>]
  </li>
<?php
  }
?>
</ul>

The static HTML at the beginning of the file output the add form. The first if block handles the add function. The second if block handles deletion. The for block list the todo items currently in the list. Note that all URLs in the output from this file point to the todo.php script.