LIS651 lecture 3 taming PHP Thomas Krichel 2005-11-12 functions • The PHP function reference is available on its web site http://www.php.net/quickref.php. It shows the impressive array of functions within PHP. • But one of the strengths of PHP is that you can create your own functions as you please. • If you recreate one of the built-in functions, your own function will have no effect. example • Stephanie Rubino was an English teacher and objects to sentences like You have ordered 1 bottles of Grosswald Pils. • Let us define a function rubino_print(). It will take three arguments – a number to check for plural or singular – a word for the singular – a word for the plural function and parameters • use the keyword "function" and declare your parameters, as in: function rubino_print ($number, $singular,$plural) { if($number == 1) { print "one $singular"; } else { print "$number $plural"; } } default arguments • Sometimes you want to allow a function to be called without giving all its arguments. You can do this by declaring a default value. For the previous example function thomas_need($thing='beer') { print "I need $thing\n"; } thomas_need(); // prints: I need beer thomas_need('sex'); // prints: I need sex rubino_print using common plurals function rubino_print ($num, $sing,$plur=1) { if($num == 1) { print "one $sing"; } elseif($plur ==1) { print "$num $sing"."s"; } else { print "$num $plur"; } } return value • Up until now we have just looked at the effect of a function. • return is a special command that return a value. • When return is used, the function is left. rubino_print with return function rubino_print ($number, $singular,$plural) { if($number == 1) { return "one $singular"; } return "$number $plural"; } $order=rubino_print(2,"beer","beers"); print "you ordered $order\n"; // prints: you ordered 2 beers. utility function from php.net function mysql_fetch_all($query) { $r=@mysql_query($query); if($err=mysql_error()) { return $err;} if(mysql_num_rows($r)) { while($row=mysql_fetch_array($r)) {$result[]=$row; } return $result;}} if(is_array($rows=mysql_fetch_all($query)) { // do something } else { if (! is_null($rows)) { die("Query failed!");} } visibility of variables • variables used inside a function are not visible from the outside. Example $beer="Karlsberg"; function yankeefy ($name='Sam Adams') { $beer=$name; } yankeefy(); print $beer; // prints: Karlsberg • the variable inside the function is something different than the variables outside. accessing global variables. • There are two ways to change a global variable, i.e. one that is defined in the main script. • One is just to call it as $GLOBAL['name'] where name is the name of the global variable. function yankeefy ($name="Sam Adams") { $GLOBAL['beer']="name"; } brewer_quiz.php: introduction <?php $brewers=array('Großwald Brauerei','Homburger Brauhaus', 'Karlsberg Brauerei','Ponter Hausbrauerei', 'Saarfürst Merziger Brauhaus','Mettlacher Abtei-Bräu','Körpricher Landbräu','Brauerei G.A. Bruch','Neufang Brauerei','Zum Stiefel'); $form_top="<form action=\"$_SERVER[PHP_SELF]\" method=\"get\"><p>\n"; $form_submit='<input type="submit" value="I try!"/>'."\n"; $form_end='<input type="hidden" name="submitted" value="1"/></p></form>'; brewer_quiz.php: form building function build_form($answer,$comment) { print "<div>Take the Saarland brewery challenge</div>\n"; print $GLOBALS['form_top']; print "<input type=\"text\" name=\"guess\" value=\"$answer\"/>"; print $GLOBALS['form_submit']; print $GLOBALS['submit_check']; print $GLOBALS['form_end']; print $comment; } brewer_quiz.php: form processing function process_form($answer,$brewers) { $r[]=$answer; foreach($brewers as $brew) { if($answer == "$brew") { $r[]='<div>Congradulation! This is correct!</div>'; return $r; } } $r[]='<div>This is a bad answer, try again!</div>'; return $r; } brewer_quiz.php main part if($_GET['submitted']) { $from_form=process_form($_GET['guess'],$brewers); } build_form($from_form[0],$from_form[1]) ; ?> working with many source files • Many times it is useful to split a PHP script into several files. • PHP has two mechanisms. • require(file) requires the to be included. If the file is not there, PHP exits with an error. • include(file) includes the file. require() and include() • Both assume that you leave PHP. Thus within your included file you can write simple HTML. • If you want to include PHP in your included file, you have to surround it by <?php and ?>, just like in a PHP script. • Here is an example to use include to build the basic web page. top.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head><title>$title</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <link rel="stylesheet" type="text/css" href="main.css"/> </head> <body> bottom.html <p id="validator"> <a href="http://validator.w3.org/check?uri=referer"><img style="border: 0pt" src="http://wotan.liu.edu/valid-xhtml10.png" alt="Valid XHTML 1.0!" height="31" width="88" /></a> </p> </body> </html> validated.php <?php $title="my basic page\n"; include("top.html"); print "<div>hello, world</div>"; include("bottom.html"); ?> trouble • $title in the top.html is not understood as the title. It reads as $title, which means "idiot" for your web user. • Even if you replace $title with <?php $title ?> $title is empty. The definition from the outer file is not seen in the included file. • So you have to split into three files, and print the title in the main file. I leave that to you to figure out. login.php & create_account.php • Both require a database that has three fields – id which is an auto_increment int acting as a handle – username is the username of the account. it must be unique and this is enforced by mySQL – password is a varchar(41) because the sha1 of the password is stored. This is 40 chars long. login.php function show_form($message) { print "<div><h1>$message</h1><h2>Login</h2> <form action=\"$_SERVER[PHP_SELF]\" method=\"post\"> <div><input type=\"hidden\" name=\"submitted\" value=\"1\" /></div><p>Username <input type=\"text\" name=\"username\" maxlength=\"15\" value=\"$_POST[username]\" /></p><p>Password <input type=\"password\" name=\"pass\" value=\"$_POST[pass]\"/></p><p><input type=\"submit\" value=\"Login\" /> Not yet a member? <a href=\"create_account.php\">Create an account</a>! </p></form></div>"; } function process_form() { $username=trim($_POST['username']); $pass=trim($_POST['pass']); $sha_pass=sha1($pass); $db=mysql_connect('localhost','krichel','laempel'); $query="SELECT * FROM beer_shop.users WHERE username='$username' AND password = '$sha_pass'"; $result=mysql_query($query); $error=mysql_error(); if($error) { return "Sorry: $query gives an error<br/> $error"; } $affected=mysql_affected_rows(); if(! ($affected)) {return "Invalid username or password";} } login.php (end) if($_POST['submitted']) { $error=process_form(); if($error) { show_form($error); } else { $user=$_POST['username']; print "<h1>Welcome to $user</h1>"; } } else { show_form(''); } create_account.php function show_form($message) { print "<div><h1>$message</h1><h2>Create Account</h2><p>Please complete the form below to create your account. </p> <form action=\"$_SERVER[PHP_SELF] \" method=\"post\"><div><input type=\"hidden\" name=\"submitted\" value=\"1\" /></div> It must be more than 5 characters and cannot be your username.</p><p> <input type=\"submit\" value=\"Create Account\" /> </p></form></div>"; create_account.php <h3>Password</h3><p> Password <input type=\"password\" name=\"pass1\" value=\"$_POST[pass1]\"/>Confirm Password <input type=\"password\" name=\"pass2\" value=\"$_POST[pass2]\"/> </p><p>The password you enter will be used to access your account. It must be more than 5 characters and cannot be your username.</p> <p><input type=\"submit\" value=\"Create Account\" /></p></form></div>"; } create_account.php function process_form() { $username=trim($_POST['username']); $pass1=trim($_POST['pass1']); $pass2=trim($_POST['pass2']); if(strlen($username)<6) { return "Username is too short."; } if(! ($pass1 == $pass2)) {return "Passwords do not match.";} $pass=$pass1; if($pass == $username) { return "Your username can not be your password."; create_account.php if(strlen($pass)<6) {return "Password is too short.";} $sha_pass=sha1($pass); $db=mysql_connect('localhost','krichel','laempel'); $query="INSERT INTO beer_shop.users VALUES ('','$username','$sha_pass')"; $result=mysql_query($query); $error=mysql_error(); 1 for key 2") { return if($error == "Duplicate entry '$username' "Sorry: Username $username is already taken, choose another."; } else {print "<h1>Thank you for registering with us!</h1>";} } create_account.php (end) if($_POST['submitted']) { $error=process_form(); if($error) { show_form($error); } } else { show_form(''); } sessions • You will recall that HTTP is a stateless protocol. Each request/response is self-contained. • Statefulness is crucial in Web applications. Otherwise users have to authenticate every time they access a new page. • Traditionally, one way to create statefullness is to use cookies. • PHP uses cookies to create a concept of its own, sessions, that makes it all very easy. cookies • A cookie is a piece of attribute/value data. A server can send cookies as value of a HTTP header Set-Cookie:. Multiple headers may be sent. • When the client visits the web site again, it will send the cookie back to the server with a HTTP header Cookie: Set-Cookie • Set-Cookie: name=value; [expires= date;] [path=path;] [domain= domain] [secure] • where – – – – name= is the variable name set in the cookie value= is the variable's value date= is a date when the cookie expires path= restricts the cookie to be sent only when requests to a path starting with path are made – domain= restricts the sending of the cookie to a certain domain – secure restricts transmission to https Cookies: • The browser compares the request it wants to make with the URL and the domain that sent the cookie. • If the path is not set the cookie will only be sent to a request with the originating URL. • If the cookie matches the request a request header of the form Cookie: name1=value1 ; name2=value2 is sent. sessions • Sessions are a feature of PHP. PHP remembers a session through a special cookie PHPSESSID. • To activate the sessions, include session_start(); at the beginning of your script, before any printing has been done. • One a session is active, you have a special super-global variable $_SESSION. Session data is stored in special files on wotan. $_SESSION • This is an array where you can read and set variables that you want to keep during the session. if($_SESSION[user_name]) { print "welcome $_SESSION[user_name]"; } else { // show users login form print login_form(); } ending sessions • At 9 and 39 past each hour, wotan deletes all session files that have not been changed for 24 minutes or more. • If you want to remove a session yourself, you can call session_destroy() in your script. visit.php <?php $top='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><title></title><meta http-equiv="content-type" content="text/html; charset=UTF-8"/> </head><body><div>'; $bottom='</div><p> <a href="http://validator.w3.org/check?uri=referer"> <img style="border: 0pt" src="/valid-xhtml10.png" alt="Valid XHTML 1.0!" height="31" width="88" /> </a></p></body></html>'; visit.php session_start(); $current=mktime(); // look at the current time if($_SESSION[last_click]) { $passed=$current-$_SESSION[last_click]; $to_print.="$passed seconds have passed since your last visit.\n"; $_SESSION[last_click]=$current; } else { $to_print="This is your first visit.\n"; $_SESSION[last_click]=$current; } print "$top\n$to_print\n$bottom"; ?> http://openlib.org/home/krichel Thank you for your attention! Please switch off machines b4 leaving!