How to write PHP script in HTML, for form results

The home of php has good documentation: This is available in many languages.

How to run php scripts

PHP is a language that is intended to be embedded within an HTML page. Mostly, the page will be normal HTML, but bits of PHP cote can be included. When the web server sees a request for a page named ending with .php, it passes it through the "PHP Hypertext Preprocessor" (that's the name of the language!), sends on the regular html, but strips out the PHP statements,  and does what they say, perhaps printing some special text at that point.

The first line of your file will normally be <html>. In fact, any html page is legal for php, which just copies it. Scripting statements must be inside <?php   .....  ?>
  1. Name the script ending with .php and put it in your public_html directory. Apache will call php to run files that end in .php.
  2. A form is typically used to call  a script, that will process the results. The form action is "yourprog.php"
  3. A link back from the script would be <a href="yourform.html">
In short, both html and php files can go in the same directory, usually public_html.

How to debug, find syntax and logic errors 

You must run PHP scripts using the web server -- http://osiris.... otherwise you will just see the php code, not its result!

So that any errors will be apparent, Apache (on Osiris) is presently configured to include error messages from PHP in it's output to the browser. If there should be any syntax errors, you will see only a line such as

Parse error: syntax error, unexpected T_VARIABLE in /home/jensen/public_html/phperr.php on line 4

In this example, there was a missing semi-colon at the end of line 3. These error messages can be cryptic, in that the compiler knows something is out of place, the actual error may have occurred earlier.
Once there are no syntax errors, you may find notices, warnings, and errors at run time. I will help you understand them.

A common notice is for an undefined variable. This is allowed, but the notice may alert you to a misspelling, perhaps $mame is undefined, because you meant to type $name.
In the following example, line 4 is:
print "hello $fuzzy world";

Notice: Undefined variable: fuzzy in /home/jensen/public_html/phperr.php on line 4
hello world

This seems all right, it is logical to print nothing if no value was given. Users will find such notices annoying, so once you have tested your script, turn them off by including the statement: (read ^ as "except")
error_reporting(E_ALL ^ E_NOTICE);  // will show all messages except notices --OR
error_reporting(0); // suppresses all messages -- include this when finished

Alternatively, you can test for an undefined variable with isset():

if (isset($fuzzy))			// balance the (( ))'s
print "hello $fuzzy world"; //might not print anything

Include comments in your script, to explain what you are doing. Comments start with // and continue to the end of the line. See above examples.

Getting form data in php:

PHP puts the form data into array variables. Depending on the form's method, the data is in either $_POST or $_GET. If you don't care, values from both are also put in $_REQUEST. Each of these arrays is indexed by strings, which are the names of each form element. So if you have <input name="name"> in the form, $_REQUEST['name'] will be the value that the user typed in.

Caution: Select multiple

If the query string contains foo=apple&foo=arrow then $_REQUEST['foo'] will be either 'apple' or 'arrow', but not both. The PHP solution is to use name="foo[]" in the form instead.
	<input  name="name">
<select name="foo[]" multiple>
Then $_REQUEST['foo'] will itself be an array, and you can go through it with foreach This is a loop statement, which does the following print statement once for each element of the inner array.
	$name = $_REQUEST['name'];
print "Hello, $name <br>";
foreach ($_REQUEST['foo'] as $item)
print " You selected $item<br>";

Checking for incomplete data

Sometimes you may want to require a field to be filled in. An if statement makes a test, and either executes or skips the next statement, or block of statements enclosed in {curly brackets}. This example tests for $name being blank, and stops the script with a message. You could also continue after printing a warning message.
if ($name == "")
die("Please go back and fill in your name");

Writing as text/html:

Be sure to use html encoding for any context in which it is expected. This includes new lines, which are simply "whitespace" to html, unless you add a <br> tag, or you enclose all of the "plain" text in <pre>   </pre> tags, which preserve the spacing of all "whitespace". This is good for program listings. But even here, you need to encode <, >, and & as entities, because some tags are recognized inside of <pre>
How? PHP has a function for just about anything you would commonly do. I found these in "String Functions":
$vh = htmlspecialchars($value); 
// '&','<','>' and '"' are encoded to print properly
$vh = nl2br($vh);
// adds <br> to show newlines (may be in a textarea)

"The Greeks have a word for it" (PHP has a function for it)

Any bit of code that one might want to execute repeatedly can be packaged as a function. PHP has a large number of read-made functions for a wide variety of common tasks. We have just seen 2 of them. You can also define your own functions.

A function takes some number of arguments (values passed in to it), performs some actions using the arguments, and generally returns a result. A function is recognized as some name, followed by a pair of (parentheses), which enclose the arguments. A function generally returns a single result. The result can be ignored, stored in a variable, or used in another statement, such as printing it, or as an argument of another function. For example, printing in html could be done with:

print nl2br( htmlspecialchars($value) );
// echo a value formatted for html display, including line breaks

Once you know the name of a function, it is easy to find out the details. Just type the name in the search area of the PHP website, et voila! So I will now give examples, without a full description. If you don't know the name, the manual groups them into categories, such as "File functions", look in these for lists with brief descriptions.

As an example of writing your own function, I have devised a function for you to use, that adds html text to a variable, so you can call it several times, then use the resulting (long) string, perhaps more than once. See the add_html(&string, string) description.

Writing to a file:

Your file may be either (plain) txt, or html. Write accordingly, see above.
You must always create your file and make it writable before executing your script, because the web server is run by the user "apache", but only you can create a file in your directory.
ssh to osiris, the easiest way to create a file is to 'touch' it.
	touch myguestbook.txt
chmod a+rw myguestbook.txt
Alternatively, you can use Places | Osiris -> File | Create | Empty file and then, for that file, Properties | Permissions, others can read and write.
The function fopen() opens a named file. You may need to give the complete path name (I think just the file name will do, if it is in the same directory). In the script you need to open the file for writing or appending (writing starting from the current end), write what you want, then close. (other modes are 'r', 'w','r+','a+', the '+' means both read and write) $guest is the "file handle", used for subsequent file operations. You can do as many fwrite()'s as you wish, then fclose(). Don't repeatedly close and reopen the same file!
$guest = fopen ("myguestbook.txt","a"); //open for appending
fwrite($guest, "Hello world\n");
fwrite($guest, "How's your $global warming?\n");
fclose ($guest); // all done, save the file
// can't fwrite any more

In case you want to print (or fwrite) the date and time, use the date() function. The argument gives the "format," each letter stands for some element, such as 'm' for month (as a number). Try this:

   print date("D, d M Y -- H:i:s\n");

Sending mail

Mail is sent by the PHP mail() function. Its arguments are: the To: address, the subject, the message text [and optionally other headers]. In the sample, I have assumed that $email is your address, and $message is the (multi-line) text you want to send. (such as the form results)  $ok would be false if there was trouble detected in sending the mail.
$ok = mail ($email,"Welcome to my class",$message,
"From: Your Name<>\nReply-To:");

Please do not sent email to anyone other than yourself, nor to a non-existant address. Do not use an <input> to determine the address.

Acessing a database (for csc107, see also part 6)

PHP has a set of functions for each kind of database. We have PostgreSQL on osiris, so use the functions whose names start with pg_ . If you should change databases, to MySQL, say, you would have to replace all pg_ with mysql_.

You connect to a database (on osiris), do any number of 'queries', look at the results of select queries, and close the connection (or else it is closed at the end of the script.) Here is a commented example:

$conn=pg_connect ('dbname=timetable') or die ('Connect failed ');

$query = "SELECT givenname, familyname FROM students"
$result = pg_query($query) or die("query failed".pg_last_error());

// print results, similar to next query ...

$query1 ='SELECT * FROM courses where prof=$1'; // will come from form
$result = pg_query_params($query, array($profname))
 or die("query failed".pg_last_error());
print pg_num_rows($result) . " rows found for $profname<br>\n";

while ( $line = pg_fetch_assoc($result) )
foreach ($line as $key => $value)
print "$key = ".htmlentities($value, ENT_COMPAT, 'UTF-8')."<br>\n";

/* Free resultset */

$query2 = 'INSERT into students (given, family, linux) values ($1, $2, $3)';
$result = pg_query_params($query2, array($g, $f, $linux))
 or die("query failed".pg_last_error());
// (could fail on duplicate primary key )
print pg_affected_rows ($result) . " rows inserted for $linux<br>\n";
// note: use this, not num_rows, for insert, update, delete queries

You will note the 'die' syntax if anything goes wrong. This will show you the error message from postgres.
Do NOT construct a query using any form data, use pg_query_params instead.

In the above example, pg_query_params  does 3 things. It safely escapes any apostrophes (') in the data, puts single-quotes (') around each value, and then puts the results in place of $1, $2, etc. The last arguement must be an array with the same number of elements as there are placeholders.

L in Jensen,