Next Previous Contents

21. PHP Tutorial

Visit the following PHP tutorial sites -

In this tutorial we assume that your server has support for PHP activated and that all files ending in .php are handled by PHP. If you are using Apache then you should edit httpd.conf and make appropriate changes to enable PHP.

Your first PHP-enabled page: Create a file named hello.php and in it put the following lines:


<html>
<head> 
<title>
PHP Test</title>
</head>
<body>
<h1>
This is an example of php script. 
<br>
Below, you will see one line saying 'Hello World' and 'foo is foobar':
</h1>
<?php 
echo "Hello World"; 
$foo = "foobar";
echo "<br>foo is $foo";
?> 
</body> 
</html>

Copy this file hello.php to the directory known to Apache, like /var/www/html which is also known as DocumentRoot in httpd.conf file. Now, to run this example, bring up a web browser and type the URL http://localhost/hello.php or you can type http://127.0.0.1/hello.php. But make sure you bring up Apache web server on your system. When you run the example you will get an output like:


This is an example of php script. 
Below, you will see one line saying 'Hello World' and 'foo is foobar': 

Hello World
foo is foobar 

If you get some errors or if you see the file with tags then your Apache Web server may not be working properly or PHP is not enabled.

Note that this is not like a CGI script. Think of it as a normal HTML file which happens to have a set of special tags available to you.

If you tried this example and it didn't output anything, chances are that the server you are on does not have PHP enabled. Ask your administrator to enable it for you.

The point of the example is to show the special PHP tag format. In this example we used < ?php to indicate the start of a PHP tag. Then we put the PHP statement and left PHP mode by adding the closing tag, ? > . You may jump in and out of PHP mode in an HTML file like this all you want.

We are going to check what sort of browser the person viewing the page is using. In order to do that we check the user agent string that the browser sends as part of its request. This information is stored in a variable. Variables always start with a dollar-sign in PHP. The variable we are interested in is $HTTP_USER_AGENT. To display this variable we can simply do:


      <?php echo $HTTP_USER_AGENT; ?>

For the browser that you are using right now to view this page, this displays:

Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)

There are many other variables that are automatically set by your web server. You can get a complete list of them by creating a file that looks like this:


      <?php phpinfo()?>

Then load up this file in your browser and you will see a page full of information about PHP along with a list of all the variables available to you.

You can put multiple PHP statements inside a PHP tag and create little blocks of code that do more than just a single echo.


      <?php
      if(strstr($HTTP_USER_AGENT,"MSIE")) {
          echo "You are using Internet Explorer<br>";
      }
      ?>

We can take this a step further and show how you can jump in and out of PHP mode even in the middle of a PHP block:


        <?php
        if(strstr($HTTP_USER_AGENT,"MSIE")) 
        {
                ?>
                <center><b>You are using Internet Explorer</b></center>
                <?
        } 
        else 
        {
                ?>
                <center><b>You are not using Internet Explorer</b></center>
                <?
        }
        ?>

Instead of using a PHP echo statement to output something, we jumped out of PHP mode and just sent straight HTML. The important and powerful point to note here is that the logical flow of the script remain intact. Only one of the HTML blocks will end up getting sent to the viewer. Running this script right now results in:

You are using Internet Explorer

Dealing with Forms

One of the most powerful features of PHP is the way it handles HTML forms. The basic concept that is important to understand is that any form element in a form will automatically result in a variable with the same name as the element being created on the target page. This probably sounds confusing, so here is a simple example. Assume you have a page with a form like this on it:


      <form action="action.php3" method="POST">
      Your name: <input type=text name=name>
      You age: <input type=text name=age>
      <input type=submit>
      </form>

There is nothing special about this form. It is a straight HTML form with no special tags of any kind. When the user fills in this form and hits the submit button, the action.php3 page is called. In this file you would have something like this:
      Hi <?php echo $name?>.  You are <?php echo $age?> years old.

Surprise!! The $name and $age variables are automatically set for you by PHP !!

21.1 Primer on PHP Sessions

This section is written by Ying Zhang .

Before we begin, let's quickly go over the concept of a session and the reason we need it. It's hard (for me) to define what a session is exactly, so let's use an example that should be very familiar to you -- logging in to your computer and using it every day. After you log in, your computer knows who you are. Every action that you perform is done so with your name.

So what's so special about that -- we take it for granted every time we have to login to any system. What's the big deal with doing this on the web? Well, the web (or specifically, the HTTP protocol) is connectionless. That means each request made to a web server is independent of all the other requests. Whereas your computer keeps information about you in memory and knows when you log in and out, a web server doesn't. A web server simply waits for requests and sends responses.

Let's illustrate this a little bit:


John Doe           __________         Jane Doe 
  1               |          |            2
  3  ------------>|web server|<---------- 4
  5               |__________|            6

Let's say we only have two people, John Doe and Jane Doe, accessing MyMarket, and their actions are like this:

  1. John looks at the product catalog.
  2. Jane looks at the product catalog.
  3. John adds an item to his basket.
  4. Jane adds an item to her basket.
  5. John goes to the checkout.
  6. Jane goes to the checkout.

Since HTTP is connectionless, each request is completely isolated from the other requests. So how does the server know who's doing what? How does the server know that actions 1, 3, 5 are from John, and actions 2, 4, 6 are from Jane? Well, to make a long story short, the web server doesn't have to know. It can continue on happily responding to requests, session management has to be done with the backend scripting language.

What we need is a way to group together requests by the same person into the same session. This is where PHP4's session management capabilities come in. It can group together requests made from the same source (eg. client's browser) into the same session, we have to provide the smarts to associate users with sessions.

In other words, PHP4's session management can tell us requests 1, 3, and 5 belong to the same session (call it session A). Our application has to know that session A is owned by John Doe.

21.2 Session Management in PHP4

PHP4 adds some session management functions that make our life easier when dealing with sessions. The ones we are interested in are:


session_start(); 
session_register();

session_start() is used to start up PHP4's session management capabilities; you need to call it before you use any of the other session functions. session_register() is used to tell PHP which variables to track in the session. A typical call to these functions would look like this:

session_register("SESSION");

This tells PHP to start up the session manager, and tells PHP that the variable called SESSION is a session variable. You can register as many session variables as you like, but I prefer to only register one session variable called SESSION, and anything I need persistent I put into this variable. For example, I like to say:


session_register("SESSION");
$SESSION["var1"] = 5;
$SESSION["var2"] = 6;

instead of


session_register("var1");
session_register("var2");
$var1 = 5;
$var2 = 6;

because after you register lots of session variables, you tend to forget what they were, well, at least I do :).

Anyhow, by now you probably want to see some code in action, so create a script called session_test.php somewhere accessible, and put into it:


<?
session_start();
session_register("SESSION");

if (! isset($SESSION)) {
        $SESSION["count"] = 0;
        echo "<li>Counter initialized, please reload this page to see it increment";
} else {
        echo "<li>Waking up session $PHPSESSID";
        $SESSION["count"]++;
}
echo "<li>The counter is now $SESSION[count] ";
?>

Fire that up in your browser, the first time you hit the page, it should say " Counter initialized, please reload this page to see it increment". Each time you reload it, the counter value should increment by one. You will also see the session ID. If it does, then hurray, your PHP4 session manager works :)

So how does this work? Well, when you call session_start(), PHP4 determines a unique session ID for the client. This session ID is an MD5 hash of something (not sure what), and is either stored in a cookie on the client's PC or is propagated in the URL.

Now each time that client makes a request, PHP4 will read this session ID and load up the data for the session. When you call session_register(), you are telling PHP4 which variables you want kept in the session. Each page that loads up, the previous values for the registered variables will be reloaded, and each time the page ends PHP4 will save the values of the registered variables.

By default, PHP keeps track of the sessions in temporary files in the /tmp directory. If you leave this set to a world-readable directory, such as /tmp (the default), other users on the server may be able to hijack sessions by getting the list of files in that directory.

session.save_path defines the argument which is passed to the save handler. If you choose the default files handler, this is the path where the files are created. Defaults to /tmp.

Take a listings and see for yourself:

You will see something like this:


-rw-------   1 apache   web            10 May  7 15:27 sess_6dd9ea8e61cd49cd3ad6de8c8b8885e8
-rw-------   1 apache   web            10 May  7 19:49 sess_7d7f97afb6759948f554b00272494e52
-rw-------   1 apache   web             6 May  9 01:00 sess_8ab78830e151add9d79b628958ce4eb9
-rw-------   1 apache   web            31 May  9 11:41 sess_a3058a6bb1baf57f565c3844c8810f4b
-rw-------   1 apache   web            30 May  9 11:42 sess_c379faad83ad3dc8ab6d22c14dbab3b4
-rw-------   1 apache   web             6 May  8 01:00 sess_cd68a5054241aff1a8157c289683e869
-rw-------   1 apache   web            34 May  7 15:17 sess_cd97e41912b28c44cc0481b7d978cb61
-rw-------   1 apache   web            42 May  9 11:23 sess_d1285edd0c951c70b1aec17a5f602fc0
-rw-------   1 apache   web            30 May  9 11:42 sess_da93f6e19b6be01257d7a6453766a23d
-rw-------   1 apache   web            42 May  7 21:26 sess_e837123c1af78c538e89b47030fde337

Each one of those files is a session, let's take a look at one of them (note, you probably have to su to root to peek inside a session file). Tip: don't just cut and paste the following commands, you need to specify the name of a real file:


# more /tmp/sess_a3058a6bb1baf57f565c3844c8810f4b

You will see something like this:


SESSION|a:1:{s:5:"count";i:234;}

Does that look familiar? It should if you've ever used the serialize() and unserialize() functions in PHP. If not, don't worry about it. Anyhow, I just wanted to illustrate how sessions were stored. You can rewrite the PHP session handlers to store sessions into a database or whatever else, but that's beyond the scope of this tutorial (but it's not hard at all).

21.3 Session Propagation

There are two methods to propagate a session id:

The session module supports both methods. Cookies are optimal, but since they are not reliable (clients are not bound to accept them), we cannot rely on them. The second method embeds the session id directly into URLs.

PHP is capable of doing this transparently when compiled with --enable-trans-sid. If you enable this option, relative URIs will be changed to contain the session id automatically. Alternatively, you can use the constant SID which is defined, if the client did not send the appropriate cookie. SID is either of the form session_name=session_id or is an empty string.

The following example demonstrates how to register a variable, and how to link correctly to another page using SID.

Example : Counting the number of hits of a single user


<html>
<h1>Example : Counting the number of hits of a single user</h1>
<br>
<php
session_register ("count");
$count++;
?>

Hello visitor, you have seen this page <?php echo $count; ?> times.<p>;

<php
# the <?=SID?> is necessary to preserve the session id
# in the case that the user has disabled cookies
?>

To continue, <A href="nextpage.php?<?=sid?>">click here</A>
<html>

The <?=SID?> is not necessary, if --enable-trans-sid was used to compile PHP.

Note: Non-relative URLs are assumed to point to external sites and hence don't append the SID, as it would be a security risk to leak the SID to a different server.

21.4 User Management and Privileges

Okay, we've spend enough time on PHP4's session management, all you really need to get out of that was the two functions session_start() and session_register(). Let's get back to the issue of keeping track of users.

PHP can help us keep track of sessions, and group requests from the same session together. Now, we have to do our part and associate user accounts with these sessions. We will use a variable called SESSION["user"] to keep track of user information. When a user logs in, we will put their information into this variable. As long as this variable is defined, we will assume that a user has logged in. When a user logs off, we will clear out this variable.

Specifically, we will keep the following information about the user:


SESSION["user"]["username"] This is the user's login ID (their nick name if you will), and it is how we tell users apart from each other. 
SESSION["user"]["firstname"] The user's firstname. 
SESSION["user"]["lastname"] The user's lastname. 
SESSION["user"]["email"] The user's email address. 
SESSION["user"]["priv"] The user's privilege level.

Let's talk a bit about the privilege levels. We are going to have two levels of security: (1) normal customers and (2) administrative users. Normal customers can use the system, browse through the catalog, and do other customer functions. Administrators can do everything a normal user can do, but also has the ability to perform system administrative functions. In real life, there are probably many more privilege levels that you want defined but we are going to keep things simple here.

This is all fine and dandy, but where do we get this user information from? We need to have a way to store all the users on the system, and the perfect place for that would be in the database. We're going to create a users table to hold all our users.

21.5 Step1: Creating the Users Table

Start up database server and login to database. Let's create the user table:


psql> CREATE TABLE users (
->   username     char(16) not null,
->   password     char(32) not null,
->   priv         char(5) not null,
->   firstname    varchar(64) not null,
->   lastname     varchar(64) not null,
->   email        varchar(128) not null,
->   phone        varchar(32) not null,
->   address      varchar(255) not null,
->   PRIMARY KEY (username),
->   UNIQUE email (email)
-> );

Notice the constraints we've put on the users table, the username is the primary key (which makes sense, you should be able to identify a user record based on the username). The email address has a unique constraint as well because we don't want duplicate email addresses.

Now let's add a record to create the root user with the password password:


psql> INSERT INTO users VALUES (
->    'root',
->    '5f4dcc3b5aa765d61d8327deb882cf99',
->    'admin',
->    'System',
->    'Administrator',
->    'root@mymarket.com',
->    '555-5555',
->    '123 5 Avenue'
-> );

Notice the password looks a bit wierd, 5f4dcc3b5aa765d61d8327deb882cf99. This is the MD5 hash of the the word "password", I won't go into details here, but the important thing to note is that it's a one-way algorithm and it always produces a 32 character string.

That's it, we have a users table to track our users, and one administrative account so we can try logging in and out of the system using the example tar file (download the example tar file from http://www.devshed.com/Server_Side/PHP/Commerce1 ).


Next Previous Contents