A Brief PHP Tutorial
by John Fortman: http://faub.keenspace.com/
October 09, 2003
First: PHP Manual
(or here if your language of choice is not
English.)
I do not own any PHP books because I have not seen a point in doing so. The
manual on the PHP site is an excellent reference.
Terotrous and Phalanx started me writing this page. It seems that mastery of PHP-fu is not as common as one could hope. Tagboard.net started all this with their fun little web utility. The basic idea was that anyone viewing your site could leave a short message (200 characters), their name and maybe an email address or link. Useful for bloggers and webcomics alike. I had one for about a month and a half. The problem was, I got the free version. Tagboard.net is so popular that it's having bandwidth problems so, my tagboard would disappear right at about the time I was doing the whole newbie dying for attention thing. The end result, I wrote one and put it on my freeshell site. Lonestar.org is a free BSD shell account with 100 megs of webspace. They run an Apache server with mod_php among other things. In other words, I can host my PHP scripts here, edit and test them online.
For those not fortunate enough to have either a school unix account (my MU account also serves PHP scripts) or another host that serves PHP, I suggest dual booting Linux. You can install a webserver with PHP in less than 200megs if you're very careful and don't install X. I will not get into how to install Linux and PHP on your machine. There are many other sites more qualified to to that than I am: The Linux Documentation Project, Linux Questions, and others I can't find at the moment.
- Linux ISO (installation CDs!)
- Slackware Linux (currently 9.1)
- RedHat Linux (currently 9)
- Mandrake Linux (currently 9.2)
- Linux.org (checkout the applications link)
Okay, done with the lead in. Finally.
The Tagboard
Get the Code
It's on the web. You may as well have a look at it. I don't consider it to
be anything special and it certainly doesn't have all the features of the
tagboard.net utility.
This isn't a GPL release or anything official like that. I can and probably
won't take the code down at any time. I wrote it, even if I did steal the
ideas from anywhere I could find them so, please please please keep the
copyright info around. I would like to get some credit for this somehow.
You're not restricted from using the code but it's not really that safe. If
you break your system with it, don't bother me about it.
That said. . .
The Tutorial
Question: Does my web host serve PHP?
No idea. However, you can check very easily. Create a short PHP program named phpcheck.php or something similar. Notice the ".php" extension. Technically this could be ".php2" or ".php3" or ".php" depending on the version of PHP that is active. You might test these as well. The different versions of PHP do have different capabilities so be careful.
<?php
phpinfo();
?>
Save this to your server and call it up like you would a regular HTML page. If you get something like this, then you're good to go. Otherwise, continue testing extensions or find a server that will host PHP.
Question: I don't know how to program. Can I still use PHP? Are there any script generators out there to help me?
Sorry, despite what the Visual Basic world would have you believe, you
really do need some coding experience to get things done on the web. PHP in
specific was written by scary developers on archane text editors like vi or
emacs and their powers are great. They have no time for silly interfaces
with bells and dropdowns. In other words, I don't really know. I've never
looked.
Still, if you want something done in PHP, Perl, Javascript or whatever,
somebody else has probably had the same idea. Search Google and most likely
you'll find a pregenerated script.
Question: I want to make a website with the same menu/title bar/footer on every page but I don't want to use frames.
My first PHP site did this very thing. It's fairly simple really.
- Write the header, footer, and body text of your site in separate files. Name them header.block, footer.block and body.block or something like that. Doesn't matter really as long as you know the file name.
- Now the PHP script to combine them all (combine.php):
<?php
include("header.block");
include("body.block");
include("footer.block");
?> - Load combine.php in your browser and the three blocks of HTML will be automagically combined.
Problem: Your PHP code freaked when I tried to include my header.block. What's the deal?
At the top of your header.block file, you probably have something like:
<? xml version="1.0"
encoding="iso-8859-1"?>
Notice that PHP also uses <? ?> to denote blocks of executable code.
You can either remove the xml declaration and live without it or you can
write it out using PHP:
<?php
echo "<" . "? xml version=\"1.0\"" .
"encoding=\"iso-8859-1\"?" . ">\n";
include("header.block");
include("body.block");
include("footer.block");
?>
Notice the < and ? are separated. PHP's write command is "echo" just like a bash shell script. Several other commands work as well: "print" (as in perl) and others. Check the docs for more info. The "." operator is actually string contatenation. Don't ask me, I didn't write the thing. Also notice that the quotes are switched out (\") just like Javascript or C.
Problem: This is great and all, but it only works for one page.
Now PHP gets interesting. CGI stands for Common Gateway Interface. It's
the method that websites use to handle form data such as the tagboard above
(when it's not being taken care of locally with Javascript). What we want
to do with PHP is pass some parameters to the script that will make it
decide which page to load.
First, some good CGI
variables:
- QUERY_STRING: Sometimes you'll see a ? in the address bar string.
The data that follows the ? are parameters with the following format:
name=value&name=value
Spaces are converted to the "+" character. Special characters are converted to a %### notation. In other words, this string is a pain to decode. The nice thing about it is we don't have to. PHP does it for us. - REMOTE_ADDR: This is the IP address (or closest proxy) for the browser viewing your site. You can save this.
- HTTP_USER_AGENT: This is the string that identifies the type of
browser, operating system and general capabilities of the agent viewing the
site. It can be used to tailor the site to the viewer's needs. It can also
be used by unscrupulous parties (Microsoft) to prevent certain browser types
from viewing your site. (As recently as this year, Slashdot had articles
about Microsoft creating a different page for Opera browsers than it did for
IE or Netscape browsers. Not that Opera was incapable of viewing the MSN
page as is. Microsoft was literally sending a mangled page!)
Your user agent string will look something like this:
"Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4a) Gecko/20030401"
PHP references these variables with a couple global variables: $_GET, $_POST and $_SERVER. The first two describe the form method parameter. (ex. <form method="post") The third gives PHP direct access to the CGI variables listed above. (ex. $_SERVER['HTTP_USER_AGENT'])
It is possible to fake a GET form query using a
hyperlink:
<a
href="combine.php?loadpage=body.block">Body</a>
So now our PHP code will look like this:
<?php
$page = $_GET['loadpage'];
if( strlen( $page ) == 0 ) $page = "body.block";
echo "<" . "? xml version=\"1.0\"" .
"encoding=\"iso-8859-1\"?" . ">\n";
include("header.block");
include( $page );
include("footer.block");
?>
A large amount of error checking code can go in here. The above code is NOT SECURE IN ANY SENSE OF THE WORD!!! Do not use it. This code allows an unscrupulous individual to include /etc/passwd as the body of the HTML page. That's a bad thing.
Question: That's great but how did you make the tagboard?
First we need to discuss some file system issues. The tagboard will not work unless you have write access to at least one file on the website. If you don't have shell access to the server, ftp might work. The trick is that your FTP needs to have a chmod function that will change the permissions of a file on the web host. The linux command-line ftp client can do this (1st column, fourth from the bottom):
ftp> ? Commands may be abbreviated. Commands are: ! debug mdir sendport site $ dir mget put size account disconnect mkdir pwd status append exit mls quit struct ascii form mode quote system bell get modtime recv sunique binary glob mput reget tenex bye hash newer rstatus tick case help nmap rhelp trace cd idle nlist rename type cdup image ntrans reset user chmod lcd open restart umask close ls prompt rmdir verbose cr macdef passive runique ? delete mdelete proxy send ftp> put tagboard.dumpfile * FTP stuff ... ftp> chmod 666 tagboard.dumpfile * Now you know this is a bad thing 8) ftp> bye
The Windows ftp client cannot. I do not use any GUI ftp clients so it's up to you to check those.
The basic idea is to set global write access to the file you want to save the tags to. Okay, warning bells and sirens should be going off in your head right about now. Global write access on a public website is a BAD thing. There has to be a better way to do it, but I haven't found it yet. The reason we need global write access is because PHP scripts execute as the user: nobody:nouser. This user has almost no permissions to do anything with any of the files on your site except read them. This is a good thing. It would be best to keep it that way, but that is completely impossible if we want to save information to the web.
Another (much better) option would be to use a database to
store the tags. A simple query would be enough to build the contents of the
tagboard:
SELECT TOP 10 FROM tagboard ORDER BY date
DESC
A database is great but not always readily available. You generally need to
request one and it's particularly difficult to maintain if you don't have
access to the server. Try backing it up for example.
A simpler method is to use a flat text file as your database. PHP has enough power to parse the socks off a text file and that is why we need global write access.
PHP code to read and write a file looks a lot like C. There are other ways to read and write a file with PHP but I started with C so that's what I use:
function LogFile( $log, $data ) {
/* Simply appends the text $data to the end of the file $log.
* Nothing special.
*/
$exists = file_exists( $log );
$fd = fopen( $log, "a" );
if( $fd ) {
fwrite( $fd, $data, strlen( $data ));
fflush( $fd );
fclose( $fd );
return true;
} else {
return false;
}
}
This block of code points out several things about PHP code that one should keep in mind:
- You can make PHP look a LOT like C, structure-wise. However, PHP takes after Perl in a lot of ways.
- All variables are prefixed with a $, just like in Perl. According to Dilbert, if you don't have the $, you don't get paid.
- There are NO datatypes in PHP. As a matter of fact, PHP is so flexible with variable data that formatting a text string is as simple as putting double quotes around the string. ("Text $variable Text") Again, this is just like Perl.
- PHP can have functions. No, it doesn't matter what order the functions are declared in. Yes, you can write a bunch of functions to another file and include the file in the any number of others. The method for doing this is the same as combining the blocks of HTML code. (include("util.php");) If you try to include a file twice you will get an error. If you include a file that has already included util.php and then include("util.php") you will get an error. Be careful with nested includes.
- 0 is an integer, a boolean and an error code in PHP. Check the docs for function return codes.
Notice that the function above would be all you needed if
you wanted to add tags to the BOTTOM of the list. It's a nice, quick
and easy function but it doesn't do what we want.
The real trick here is to read all the data in the file to memory, write the
new tag block, then write all the original data. That's a pain to code and
highly inefficient in terms of stress on the server. Luckily, a tagboard
isn't meant to handle a couple thousand posts a minute. If it comes to
that, this tagboard is getting taken down and I'm getting a real forum.
I'm not going to list the code to reverse the order of the tags. It's in
the .tgz file I linked at the top of this list.
Basically, we're done. That's it. You don't need that much more code to produce the tagboard. The only other code you need is for error checking the data as it comes in. Believe it or not, the form itself does a lot of the work.
Hey! You didn't mention anything about the tag data itself. What does that look like?
Simple:
<div class="comment" title="Oct 09 2003 09:06:28 pm">
<span class="user"><a href="mailto:jfortman@hotmail.com">faub</a></span>:
<span class="message">I might be able to write up something. If you have a background in C or perl, you should be fine with PHP, though.</span>
</div>
The trick is to define a structure that is easy to parse.
- In this example, that last </div> means that I've reached the end of a tag block. Using $s = fgets( $fp ); I can strcmp( $s, "</div>\n" ) == 0 to determine if I've read an entire block.
- The date you see is the PHP date() command. You will need to look at the docs for this one. It's cryptic.
- "faub" here is from the first input box. The string is copied as is.
- The email address is passed from the second input line of the form. Notice that you don't need to add the mailto:. The PHP searches for a "@" in the input string using strpos(). If it finds one, it adds the mailto:. If not, no mailto:.
- The message text is copied straight from the textarea.
- Grabbing these is almost identical to selecting the body text for your combined HTML page. I say almost because it uses the $_POST variable instead of $_GET. (for example: $_POST['name'] references the name input of the form)
- Notice that the formatting is done with CSS classes. This means the resulting tag block can look like anything you want. Neat huh?
Closing Comments
It's like 2:00am so I'm going to stop here. A lot of what you need to know about PHP can be discovered through experimentation. If you don't know how to do something, browse the manual. Most likely, you'll find something interesting there.
Good luck.