![[ Register ]](/images/navbar/register.gif)
![[ Applications ]](/images/navbar/applications.gif)
![[ Documentation ]](/images/navbar/documentation.gif)
![[ Distributions ]](/images/navbar/distributions.gif)
![[ Download Info ]](/images/navbar/download.gif)
![[ General Info ]](/images/navbar/geninfo.gif)
![[ Book Store ]](/images/navbar/bookstore.gif)
![[ Courses ]](/images/navbar/courses.gif)
![[ News ]](/images/navbar/news.gif)
![[ People ]](/images/navbar/people.gif)
![[ Hardware ]](/images/navbar/hardware.gif)
![[ Vendors ]](/images/navbar/vendors.gif)
![[ Projects ]](/images/navbar/projects.gif)
![[ Events ]](/images/navbar/events.gif)
![[ User Groups ]](/images/navbar/usergroups.gif)
![[ User Area ]](/images/navbar/user_area.gif)

![[ About Us ]](/images/navbar/aboutus.gif)
![[ Home Page ]](/images/navbar/homepage.gif)
![[ Advertise ]](/images/navbar/advertise.gif) |

| Intermediate Level User Linux Course |
|---|
Web developmentWe've dealt with how to set up and configure Apache and MySQL. Now we
can use these tools in connection with others to provide web services
to our office, company or to the world. PHPPHP is a web scripting language created by Rasmus Lerdorf to solve some
problems he was having with is personal home page
(the initials of which are PHP). The developers of PHP maintain that
these initials stand for PHP Hypertext Processor in the GNU tradition
of recursive acronyms, so we'll take their word for it and leave it at that.
As Shakespeare famously pointed out, A rose by any other name would smell
as sweet, so whatever PHP stands for, it's a great tool for web development
and more importantly, its learning curve is not that steep compared to
other programming languages.  | PHP is currently at version 4 with version 5 reportedly on the way soon (at the time of this writing). Version 4 is a complete re-write of the original PHP language carried out by Zend Technologies Ltd, a company based in Israel. We will be dealing with PHP version 4 in this lesson. |
Installation of PHPI hope the readers will forgive me for repeating many things, but as we have
seen with many other programs and server daemons, most major Linux distributions
will allow you to install PHP and some accompanying modules with minimal effort. Apache module or stand-alone CGIPHP can be installed as a module of Apache (known as mod_php) or as a
stand-alone executable binary, also known as CGI. There are pros and cons
to both. I have worked with both systems and from a development point of
view, I prefer compiling it into Apache as a modules, mainly for performance
and security reasons.
PHP.net
has some
good pages
to explain some of these issues in more detail. Your distribution will normally give you the option of installing this in
one way or another. Installing PHP on your own from source code is also possible.
Using PHP as an Apache module requires you to recompile Apache itself and this
goes somewhat beyond what we can efficiently deal with in this lesson. Suffice it to say that I have not had to install PHP in this way in over 3 years, so
chances are that you will just indicate that you want to use PHP during your
distribution's install process and you will have it when you're finished. You may also find that some add-ons to PHP might come in handy. There
are modules that work with MySQL, PostgreSQL, IMAP and some other programs
plus enhancement tools like PEAR. It is my experience with Debian GNU/Linux
that you can easily choose these add-ons during the installation process
and you can then use them after without much futzing around. Just to make sure that PHP is installed to your liking, you can have a
look at your Apache httpd.conf file. Look for the following lines: LoadModule php4_module /usr/lib/apache/1.3/libphp4.so |
And <IfModule mod_dir.c>
DirectoryIndex index.html index.php index.htm index.shtml index.cgi
</IfModule> |
Also: # And for PHP 4.x, use:
#
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps |
These lines are the basic requirements so that PHP scripts are processed
by Apache. If Apache is running and you've been able to locate these lines,
then we're all set to start web development with PHP. Your first PHP scriptThose of us who have tried to learn a programming language know that
you usually start off with the archetypal 'Hello World' programs (or their
variants ('Hello Mars', 'Hello Jupiter', 'Hello Vulcan'). We all know
what these are going to do so we'll start with a more practical example.
Let's write a script to have PHP give us information about itself. Example 1. Hello PHP! <?php
// this is a comment
/* this is
* another
* comment */
// this will show us information about PHP
phpinfo();
?> |
This will give us a long page with detailed information about PHP and how
it works with our server, what it will do for us, etc. I'd say it's a tad
more interesting than 'Hello world!'. Even this small script gives us a
lot of information about actually writing our own scripts. First, you
will notice that PHP scripts begin with <:?php.
This basically tells Apache to process the rest of the script as PHP.
Skipping down to the end, you'll see the reverse: ?>
which logically means, end of script. You will also notice that
you can use two types of commentary. I prefer the // for short commentary
and /* *text *here */ for longer explanations. This is, of course, a personal
preference. Lines of code in php must end in a semi-colon (;). These
are the basics. We'll see some more requirements as we move along with
the lesson. HTML with PHPWeb browsers are designed to render content written in HTML. However, pure HTML
is just static content. Web scripting languages like Perl and in particular PHP,
which was designed after the WWW hit the public consciousness and is therefore
designed particularly for it, can really help us to make sure the information
we're providing is up-to-date. PHP can take real-time information from a
MySQL database and display it in an HTML format and provide what is called
"dynamic" content. Before we actually talk about providing this content,
let's see how PHP displays HTML. Example 2. Hello PHP! <?php
/* script to output simple HTML
* using PHP */
// show the page
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
print "<html>\n";
print "<head>\n";
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n";
print "<meta NAME=\"Author\" content=\"Michael J Jordan\">\n";
print "<meta NAME=\"description\" content=\"php\">\n";
print "<meta NAME=\"keywords\" content=\"php, html\">\n";
print "<title>Welcome to PHP</title></head>\n";
print "<body bgcolor=\"#ffffff\">\n";
print "<h2>Welcome to PHP!</h2>"\n";
print "</body>\n";
print "</html>\n";
?> |
True to my tradition of being my own worst critic, this code is neither
terribly efficient nor elegant, but it does show more important information
about how PHP works. I chose to use this because it shows how PHP acts
like a traditional programming language. Like C, for example, you'll find
that you need to place things that will be show to the user like so: You could also alternatively use: This code is not efficient because it doesn't do anything that your
run-of-the-mill page in pure HTML could do. As a matter of fact, PHP
will let us write pure HTML if we want. Example 3. Hello again PHP! <?php
/* script to output simple HTML
* using HTML in a PHP script */
// create page
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta NAME="Author" content="Michael J Jordan">
<meta NAME="description" content="php">
<meta NAME="keywords" content="php, html">
<title>Welcome to PHP</title></head>
<body bgcolor="#ffffff">
<?php print "<h2>Welcome to PHP!</h2>"; ?>
</body>
</html>
<? // the end ?>
|
This is really nothing more than scattering PHP throughout an HTML
script. But we could add to it to make it a little more dynamic. Example 4. And the time is... <?php
/* script to output the time
* using a PHP script */
// get time and create variable
$myTime = date("H:i:s");
// create page
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta NAME="Author" content="Michael J Jordan">
<meta NAME="description" content="php">
<meta NAME="keywords" content="php, html">
<title>Welcome to PHP</title></head>
<body bgcolor="#ffffff">
<?php
print "<h2>Welcome to PHP!</h2>";
print "<h3>The time is <b>$myTime</b></h3>";
?>
</body>
</html>
<? // the end ?>
|
Here we've used the MySQL 'date' function to get the local time. We've
converted the result into a variable called $myTime and used this to
show the date to users. There are a lot of different options for showing the date
and the time. Check out PHP.net's fine
manual page for more options. Speaking of options, that's what
PHP is all about - options! How about choosing a greeting based on the
hour that people visit your page: Example 5. Greeting a user <?php
/* script to output the time
* using a PHP script */
// get time and create variable
$myTime = date("H:i:s");
// give the user a special greeting
$myHour = date("H");
if (($myHour > "06") && ($myHour < "12"))
{
$greeting = "Good Morning";
}
else if (($myHour > "12") && ($myHour < "18"))
{
$greeting = "Good Afternoon";
}
else if (($myHour > "18") && ($myHour < "22"))
{
$greeting = "Good evening";
}
else
{
$greeting = "Hey! You're up late!";
}
// create page
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta NAME="Author" content="Michael J Jordan">
<meta NAME="description" content="php">
<meta NAME="keywords" content="php, html">
<title>Welcome to PHP</title></head>
<body bgcolor="#ffffff">
<?php
print "<h2>Welcome to PHP!</h2>";
print "<h3>The time is <b> $myTime </b></h3>";
print "<h3> $greeting </h3>";
?>
</body>
</html>
<? // the end ?>
|
As you can see, we're making this page a little more dynamic each time. Greeting
the user is interesting, but it doesn't really represent anything that
you couldn't do with JavaScript, for example. But let's imagine that
those variables, instead of just displaying the date, were actually showing
information from a database - perhaps our LP collection database we saw in
the MySQL section. With PHP, you can do that. True dynamic contentThe above examples were true dynamic content in that we didn't have to
manually change the time (which would be a chore indeed!) or the
greeting. But in terms of providing dynamic content, they represent only the
most infinitesimal piece of the tip of the proverbial iceberg. Where
we start seeing more of the iceberg is when we use data from MySQL or
another database package. Here's a fairly simple script to show the
data in our LP database: Example 6. Hello World - here's my album collection <?php
/* script to list the LPs in our collection
* uses DB album TABLE collection */
// get the HTML doctype declaration and metatags
require("./includes/doctype.inc.php");
// get our database connection information
require("./includes/dbinfo.inc.php");
mysql_selectdb("album");
// start page
print "<title>My Album Collection</title>\n";
print "</head>\n";
print "<h1 align=\"center\">My Album Collection</h1>\n";
print "<table width=\"98%\" cellspacing=\"2\" cellpadding=\"2\" align=\"center\">\n";
print "<tr><th>Artist</th><th>Title</th><th>Label</th><th>Released</th></tr>\n";
$query = mysql_query("SELECT artist, title, label, date_format
(released, '%d %M %Y') AS Release_Date FROM collection ORDER BY artist");
if (mysql_num_rows($query) != 0)
{
while ($row = mysql_fetch_array($query))
{
$artist = $row["artist"];
$title = $row["title"];
$label = $row["label"];
$released = $row["Release_Date"];
print "<tr>\n";
print "<td align=\"center\"><font size=\"2\">$artist</font></td>\n";
print "<td align=\"center\"><font size=\"2\">$title</font></td>\n";
print "<td align=\"center\"><font size=\"2\">$label</font></td>\n";
print "<td align=\"center\"><font size=\"2\">$released</font></td></tr>\n";
}
}
else
{
print "<tr><td colspan=\"2\">Sorry, no LPs found</td></tr>\n";
}
print "</table>\n";
print "<p></p>\n";
require ("endofpage.inc.php");
// that's all folks!
?>
|
Besides being a leap forward compared with our script that showed you
the time, it's also quite a bit more efficient. First, we've taken
our HTML doctype declaration and metatags, which should appear in
every HTML document, and we've put them in separate file. That saves
us from having all of that information in every PHP script we write.
Secondly, the database connection information goes into a separate
file as well. This is also for efficiency, but more for security.
It contains our password and that kind of information should never
be put into the script itself. As you can see, to require that a
file be included in your script, use this syntax: require ("/some/where/somefile"); |
What I've included in the three files we require is: Example 7. doctype.inc.php print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
print "<html>\n";
print "<head>\n";
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n";
print "<meta NAME=\"Author\" content=\"Michael J Jordan\">\n";
print "<meta NAME=\"description\" content=\"php\">\n";
print "<meta NAME=\"keywords\" content=\"php, html\">\n"; |
Example 8. dbinfo.inc.php $db = mysql_connect("localhost", "USER", "PASSWORD")
or die ("There was a database error"); |
Example 9. endofpage.inc.php print "</body>\n";
print "</html>"; |
The first and third files are rather self explanatory. The one
in the middle is also fairly straightforward. It includes our
database connection information and some error handling. If the
MySQL daemon were to shut down unexpectedly your users would get
some meaningful message (the message is entirely up to you). So if you load this main file into in your server's web directory,
anywhere Apache is configured to serve web pages, and then put the required
files where the path says they're supposed to be located, then you'll
be able to see something like this:
My Album Collection
Artist Title Label Released
Beatles Yesterday and Today Capitol 01 June 1966
Elvis Costello Armed Forces Rhino 05 January 1979
Police Zenyatta Mondatta A&M 03 October 1980 |
The meaty part of the script, so to speak, comes in the middle. First, we
start with the MySQL query: $query = mysql_query("SELECT artist, title, label, date_format
(released, '%d %M %Y') AS Release_Date FROM collection ORDER BY artist"); |
This is a normal MySQL query with the little trick we learned about
showing the date in a more pleasant form. Next, we make sure that there are actually entries in the table. PHP
has a statement here, mysql_num_rows, that looks for the number of
entries or rows in our table. So we set up
a conditional statement that says if the number of rows isn't zero,
then we should fetch information from the table and present it.
if (mysql_num_rows($query) != 0)
{ |
We then "fetch" the rows from the MySQL table and convert them into
an array of values: while ($row = mysql_fetch_array($query))
{
$artist = $row["artist"];
$title = $row["title"];
$label = $row["label"];
$released = $row["Release_Date"]; |
We have also converted the entries into variables to display in the table. After we render the HTML table with the variables, we add an else statement
in case we have no entries in our database table else
{
print "<tr><td colspan=\"2\">Sorry, no LPs found</td></tr>\n";
} |
That's providing dynamic content in a nutshell. Updating/Editing contentProviding dynamic web content also means being able to add to it and
edit it if necessary. We'll need to develop scripts to let us do this.
Here's one that gets that job done: Example 10. Manage my album collection <?php
/* script to edit/add/delete to the LPs in our collection
* uses DB album and TABLE collection */
// get the HTML doctype declaration and metatags
require("doctype.inc.php");
// get our database connection information
require("dbinfo.inc.php");
mysql_selectdb("albums");
// start doing stuff
/* if we find an ID
* in the hidden ID field
* it means we're doing an edit */
// the submit button will be present with edits or adds
if ($submit) {
/* if there's an ID number in the hidden field
* we're editing. If not, we're adding */
if ($ID) {
$query = "UPDATE collection SET title='$title', artist='$artist', label='$label',
genre='$genre', condition='$condition', worth='$worth', notes='$notes',
released='$released', added='$added', opened='$opened' WHERE ID=$ID";
} else {
$query = "INSERT INTO collection (title, artist, label, genre, condition, worth,
notes, released, added, opened) VALUES ('$title', '$artist', '$label', '$genre',
'$condition', '$worth', '$notes', '$released', '$added', '$opened')";
}
// do the query
$result = mysql_query($query);
print "Database changed.";
print "<p><a href=$PHP_SELF>Enter or edit more
information</A>";
} elseif ($delete) {
// delete the record we choose
$query = "DELETE FROM collection WHERE ID=$ID";
$result = mysql_query($query);
print "<p>That entry is goooooooone!\n";
print "<a href=\"$PHP_SELF\">Add or Edit LP</a>\n";
} else {
// no ID == new entry
if (!$ID) {
// print our list of albums
$result = mysql_query("SELECT * FROM collection ORDER BY title");
print "<table border=\"0\" bgcolor=\"#FFF0F0\" width=\"98%\"
cellspacing=\"1\" cellpadding=\"2\">\n";
// output the list
while ($myrow = mysql_fetch_array($result)) {
print "<tr><td><b>Album: </b>";
printf("<a href=\"%s?ID=%s\">%s </a></TD><TD>
<B>%s</B>\n", $PHP_SELF, $myrow["ID"], $myrow["title"],
$myrow["artist"]);
print "</td><td>\n";
// think twice before you offer this to users!!
print "<font color=\"990000\"><b>Delete (careful!):
</b></font>";
printf("<a href=\"%s?ID=%s&delete=yes\">YES</a>
</td></tr>\n", $PHP_SELF, $myrow["ID"]);
}
print "</table>";
}
?>
<p>
<a href="<?php echo $PHP_SELF?>">Add LP</a>
<p>
<form method="post" action="<?php echo $PHP_SELF?>">
<?php
if ($ID) {
// if editing - select a record
$query = "SELECT * FROM collection WHERE ID=$ID";
$result = mysql_query($query);
$myrow = mysql_fetch_array($result);
// this hidden field contains the ID of the entry
?>
<input type="hidden" name="ID" value="<?php echo $ID ?>">
<?php
// the HTML fields
}
?>
<h2>LP collection</h2>
<h4>Use 'add LP' to add an LP or click on the name to modify an
existing one</h4>
<p>
<table border="0" bgcolor="#ffcc99" align="center" width="80%">
<tr><td><b>Title: </b></td><td align="left">
<input type="Text" name="title" size="80" maxlength="80"
value="<?php echo $myrow["title"] ?>">
</td></tr>
<tr><td><b>Artist: </b></td><td align="left">
<input type="Text" name="artist" size="80" maxlength="80"
value="<?php echo $myrow["artist"] ?>">
</td></tr>
<tr><td><b>Label: </b></td><td align="left">
<input type="Text" name="label" size="40" maxlength="40"
value="<?php echo $myrow["label"] ?>">
</td></tr>
<tr><td><b>Genre: </b></td><td align="left">
<input type="Text" name="genre" size="40" maxlength="40"
value="<?php echo $myrow["genre"] ?>">
</td></tr>
<tr><td><b>Condition: </b></td><td
align="left">
<input type="Text" name="condition" size="20" maxlength="20"
value="<?php echo $myrow["condition"] ?>">
</td></tr>
<tr><td><b>Worth: </b></td><td align="left">
<input type="Text" name="worth" size="10" maxlength="10"
value="<?php echo $myrow["worth"] ?>">
</td></tr>
<tr><td><b>Released: </b></td><td
align="left">
<input type="Text" name="released" size="10" maxlength="10"
value="<?php echo $myrow["released"] ?>">
</td></tr>
<tr><td><b>Added: </b></td><td align="left">
<input type="Text" name="added" size="10" maxlength="10"
value="<?php echo $myrow["added"] ?>">
</td></tr>
<tr><td><b>Opened: </b></td><td align="left">
<select name="opened">
<option value="<?php echo $myrow["opened"] ?>">
<?php echo $myrow["opened"] ?> </option>
<option value="yes">yes</option>
<option value="no">no</option>
</select>
</td></tr>
<tr><td colspan="2">
<b>Notes:</b><br><textarea name="notes" cols="80"
rows="10" wrap="virtual">
<?php echo $myrow["notes"] ?></textarea>
</td></tr>
</table>
<p>
<input type="submit" name="submit" value="ok">
<input type="reset" name="reset">
</form>
<?php
}
require("endofpage.inc.php");
?>
|
This will give you a way to update your data. However, there are a couple
of things wrong with this script. One thing is the HTML, which is not
really written to be aesthetically pleasing. But since this isn't a course
in HTML, then we can overlook that. The most important thing about this
script is that it doesn't do any error checking. First, it doesn't
warn you if you've left a field blank. Though that's fairly important,
what's more important from a security point of view is the need to check
the fields for illegal characters. Characters like *<>!#\
(which look a lot like comic book swearing) can be used in conjunction
with other code to use your script to attack the machine.
Although this is probably only going to be used by you and you really
aren't going to try to crack into your own machine, it's good to get
into the habit of writing good, secure scripts. You never know when
you might be called on to do this for a public website. So let's add
a little basic security. Before we let anyone submit information, we'll
give it a check. Example 11. Re-written section if ($submit) {
// make all fields into one long string
$myFields = array($title, $artist, $label, $genre, $condition,
$worth, $notes);
$careful = implode(" ", $myFields);
// check for strange characters for security reasons
if (!ereg("[*+#\|<>@$%]+", $careful))
{
/* if there's an ID number in the hidden field
* we're editing. If not, we're adding */
if ($ID) {
$query = "UPDATE collection SET title='$title', artist='$artist', label='$label',
genre='$genre', condition='$condition', worth='$worth', notes='$notes',
released='$released', added='$added', opened='$opened' WHERE ID=$ID";
} else {
$query = "INSERT INTO collection (title, artist, label, genre, condition,
worth, notes, released, added, opened) VALUES ('$title', '$artist', '$label',
'$genre', '$condition', '$worth', '$notes', '$released', '$added', '$opened')";
}
// run SQL against the DB
$result = mysql_query($query);
print "Database changed.";
print "<p><a href=$PHP_SELF>Enter or edit
more information</A>";
}
// warn the user who enters illegal characters
else {
print "<title>Update/Add to Album
Collection</title></head>\n";
print "<body bgcolor=\"#fff0f0\">\n";
print "<h2 align=\"center\">Error</h2>\n";
print "<h3 align=\"center\">Please do not use non-standard
characters</h3>\n";
print "<h4 align=\"center\">Use your back button to
return</h4>\n";
}
} elseif ($delete) {
// delete a record |
I've re-written the section between if ($submit) {
and } elseif ($delete) { We need another 'if'
condition to check the fields in which you can freely enter
information. I have left out the Released, Added,
Worth and Opened fields. These should
be changed to drop down menus. This will eliminate the need for checks
there, as the information you can enter is limited to what the menus
give you. To make this more efficient, I have converted the contents
of the fields into one long string, courtesy of the PHP function 'implode'.
Then we'll give an error message if someone enters characters like
these *+#\|<>@$%. So this limits the user to
alpha-numerical characters and punctuation which shouldn't do any harm. More or less, we have a script that will add, edit and delete data.
Combined with the script before to show our data, we've got a
web-based data processing system written in PHP. The scripts are far
from finished, however. We need some error checking there to make
sure people don't leave things blank, use obscene words or any other
limitations we might want. We can make it a whole lot nicer looking
too. I'll let you do these things as a homework assignment! Web development with PerlWe've already talked a bit about Perl as a tool to help with system
administration, (which is what it was originally designed for) but
it's also the most widely-used language for web development on Linux
systems. Since the advent of the World Wide Web, more features have
been added to Perl to improve its use as a web scripting language. Some time ago, I wrote some scripts to create a web-based knowledge base
of Linux configuration information, mostly for my personal use.
It's sort of a cross between a set of how-tos and a FAQ. I'll be using
these scripts as examples in this lesson.  | Many people prefer PHP because it was created after the Web came into
being and since Perl came before, it supposedly is playing catch-up,
according to PHP fans. Strictly speaking, the two are capable of doing
the same things. I have found that Perl requires more coding than PHP
in general and you need to know something about accompanying code known
as Perl modules in order for you to be really proficient in Perl. PHP
seems to have more features built-in to it and a quick perusal of the
PHP manual will get you up to speed on them. Perl also may a
bit more imposing if you're new to programming. PHP on the other hand,
is not well suited to tasks such as system
administration, though PHP developers are also trying to take PHP in
that direction. These are, of course, are my personal observations
and so should be taken with that in mind. |
MySQL revisitedMySQL and Perl also make a good combination, like MySQL and PHP. Before
we start out creating our knowledge base, we'll need to set up a
database and table. I named the database 'kbase' and created this
table: +------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+----------------+
| how_to | varchar(255) | YES | | NULL | |
| level | varchar(30) | YES | | NULL | |
| category | varchar(30) | YES | | NULL | |
| answer | text | YES | | NULL | |
| keywords | varchar(100) | YES | | NULL | |
| importance | int(11) | YES | | NULL | |
| rating | int(11) | YES | | NULL | |
| modified | timestamp(14) | YES | | NULL | |
| ID | int(11) | | PRI | NULL | auto_increment |
+------------+---------------+------+-----+---------+----------------+ |
The how_to field is the field that will contain our question: 'How do
I configure ....' . I've given this plenty of room. 'level'
corresponds to the difficulty of the configuration task. 'category'
responds to the area we're dealing with (mail, x-window, kernel). The
'answer' is the explanation of how to do it and I have allowed a whole
text field. 'keywords' we can use for future searches when our data
gets voluminous. 'importance' is a field for giving a value to judge
how often we're going to doing these things. The 'rating' is a system
of showing how often we really have needed to look something up. I put
that there for my personal curiosity. You may find other field names
more meaningful. Now that you know all about MySQL, you are free to
change them. Our first script will be one to enter information in
the table. Adding dataBefore we start writing a script in Perl, we should find out where
Perl is hiding. This is important. A hosting service I once used
upgraded their server and Perl went from being /usr/bin/perl to
/some/where/else/perl. My scripts broke and my website visitors
started mailing me. The most common location for Perl in my
experience is /usr/bin/perl, and that's what will appear first
in our script. The -w part means 'warn'. This will show us warnings if our code
has some rough edges to it. Let's look at the whole script: Example 12. add.pl #! /usr/bin/perl -w
use strict;
use DBI;
use CGI;
use CGI qw(:standard :netscape :shortcuts);
use CGI::Carp qw(fatalsToBrowser);
# little routine to include external scripts
sub include {
# Include files in this directory
my $file = shift or return;
my $path = '/home/mike/www/dev/perl/incluir/';
open INC, "$path/$file" or return $!;
read INC, my $str, -s INC;
close INC;
return $str;
}
## include these files
my $MyWWW = "/dev/perl";
my $imagenes = "$MyWWW/graficos";
my $inc_dtype = include('doctype.inc');
my $inc_head = include('header.inc');
my $inc_add = include('adding.inc');
my $inc_foot = include('footer.inc');
my $inc_endpg = include('endpg.inc');
## add basic password protection
open PWD, "/home/mike/perl-lib/dbinfo";
my ($user, $pass) = split(/:/, <PWD>, 2);
close PWD;
chomp($user, $pass);
# print HTML headers
print "Content-type: text/html\n\n";
# print page
print qq |
$inc_dtype
<title>Linux Knowledge Base</title>
<body bgcolor="#ffffff">
$inc_head
$inc_add
|;
# see if we have the HTML fields
if (param()) {
# open DB connection
my $dbh = DBI->connect('DBI:mysql:dbname=kbase', $user, $pass);
my $how_to = param ("how_to");
my $level = param ("level");
my $category = param ("category");
my $answer = param ("answer");
my $keywords = param ("keywords");
my $importance = param ("importance");
# my $rating = param ("rating");
# start counting visitor rating at 0 (of course)
my $rating="0";
if (($answer =~/Microsoft/i) || ($answer =~/Gates/i))
{
print qq |
<b>Eeek! Microsoft!</b>
<p>Are you sure you want that in there?
$inc_finpg
|;
}
else {
my $sql = "INSERT INTO questions (how_to, level, category, answer, keywords,
importance, rating) VALUES (";
$sql .= $dbh->quote($how_to) . ",";
$sql .= $dbh->quote($level) . ",";
$sql .= $dbh->quote($category) . ",";
$sql .= $dbh->quote($answer) . ",";
$sql .= $dbh->quote($keywords) . ",";
$sql .= $dbh->quote($importance) . ",";
$sql .= $dbh->quote($rating);
$sql .= ")"; $dbh->do ($sql);
print qq |
<p><br>
<table align="center" border=0 cellspacing=2 cellpadding=4 width=70%
bgcolor="#990000">
<tr><td bgcolor="#ffffff"><font color="#990000"><B>FYI:
</B></td></tr>
<tr><td bgcolor="#ffffff"><p>The how-to:<br>
<font color="#0000cd"><b>$how_to</b></font>
<br> has been added to our knowledge base.</td></tr>
</table>
<p><br>
<h3 align="center">Add another</h3>
<h3 align="center">or <a href="../bin/list.pl">see the list</a></h3>
|;
}
# Disconnect from the database
$dbh->disconnect;
}
# show our data form
print qq |
<form method="get">|;
# entry fields
print qq |
<p>
<table align="center" border=0 cellspacing=2 cellpadding=4
width=80% bgcolor="#000080">
<tr><td bgcolor="#9ed5d4" colspan="2">
<font color="#990000"><b>How do you: </b></font><br>
<textarea name="how_to" cols="60" rows="3" wrap="virtual"></textarea>
</td>
<tr><td bgcolor="#9ed5d4">
<font color="#990000"><B>Difficulty Level: </B></font>
<select name="level">
<option value="NA"> NA</option>
<option value="easy"> easy </option>
<option value="involved"> involved </option>
<option value="difficult"> difficult </option>
<option value="very difficult"> very difficult </option>
</select>
</td>
<td bgcolor="#9ed5d4">
<font color="#990000"><B>Category: </B></font>
<input type="text" name="category" size="50"></td></tr>
</select></td></tr>
<tr><td bgcolor="#9ed5d4" colspan="2"><font color="#990000">
<B>Frequency of use: </B></font><font size=2></font>
<select name="importance">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<font size="2">(We will use this - 1 = a lot, 2 = sometimes 3 = not much)
</font>
</td></tr>
<tr><td bgcolor="#9ed5d4" colspan="2">
<font color="#990000"><b>Keywords: </b></font>
<input type="text" name="keywords" size="70"></td></tr>
<tr><td bgcolor="#9ed5d4" colspan="2">
<font color="#990000"><b>Explanation: </b></font>
<br><textarea name="answer" cols=60 rows=20 wrap="virtual">
</textarea><br>
</td></tr>
<tr><td align="left"><input type="submit" name="submit" </td>
<td colspan="2" align="right"><input type="reset"></td></tr>
</table>
</form>
<p><br>
$inc_foot
$inc_endpg
|;
|
As you can see, there are some significant differences compared with our
PHP scripts before. First, you'll see that we need to tell the script
to use some Perl modules. Perl modules is a system that exists to re-use code
so you don't have to write the same things over and over again in your
code.
 | There are a lot
of modules available via the CPAN (Comprehensive Perl Archive Network) system.
The easiest way to get Perl modules is to fire up a 'cpan' terminal and
install them through there. To open a CPAN terminal, type:
perl -MCPAN -e shell. If it's the first time, you'll have
to answer a few questions about your system in order to set it up. Then
you can install new modules with a command like:
install ModuleName |
First, we've said we want to use the modules 'strict'.
Basically, it requires you
to declare variables first before using them. You'll notice the variables
in the script are first declared as 'my $something'. This makes the script
run faster and in the long run makes it easier to spot mistakes. If
you type a variable wrong in the script, then the script will stop and
tell you that it can't find it. Next, we see 'use DBI'. This is the
module 'DataBase Interface' that allows us
to connect to and use MySQL. The next are the various parts of the
CGI module we're going to use. I should actually say that we could
use them. This script really doesn't take advantage of these that much.
That is to say, I could use the CGI module write my HTML with a more
Perl like syntax - something like
instead of using the
normal tags as we have here. This is a question of choice and my brain
seems to work better when HTML is HTML. The last one, fatalsToBrowser,
sends error output to the browser with a nice message asking you to
contact the webmaster of the site. This can come in handy because
you may actually be sleeping and the server might encounter problems.
If some nice website visitor chooses to paste in the error message, you
might have otherwise lost information about what was going on at the time.
You can actually customize these messages. See 'man MODULE_NAME' for
more informations on the Perl modules installed on your system. The next system is actually a little kludge I found (my thanks to whomever
wrote this) to allow me to use external files like PHP uses 'require/include'.
Files in /home/mike/www/dev/perl/incluir/ can be included in the script.
This allows me to keep my static content in another place. With this
we can re-use HTML. Next, we declare these files for use later. Next, we have another kludge to keep the passwords out of the web
directory's hierarchy. The dbinfo file just has one line
which is USER:PASSWORD. This little routine separates them
and passes it to two variables which we'll use to connect to our
database. If you skip over the block where we start creating the page,
you'll see the connection info and the 'param' fields which are there so
our HTML fields will pass the info in them to our table. But before
we pass the information, we should do a little error handling. Due to
the nature of the web app we're creating, we can't be too selective
about letting strange characters into the database. After all, this
is about configuration, so we'll definitely need to enter characters
that we would have considered illegal in the PHP examples. I've added
a little humorous block here as an example. Next you'll find where we've given a little notice when we've added the info
to our database. After, we break our connection to the database. Next we put
the html table where our fields are for entering information. You've may have
noticed that 'print qq | |; will let us put HTML code in between without
escaping the quotes with forward slashes (\) as we had to in HTML. After we
add a last few include files, we're finished with our basic script to
add information. Editing entriesIt's not enough to enter the information. We'll need to retrieve it and
to edit it if necessary (and it usually is). Let's look at some scripts
for doing those tasks. Example 13. publist.pl #!/usr/bin/perl
use strict;
use DBI;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
# needed for inclusion
sub include {
#---------------------------------------------------
# Pass in a file name to include.
my $file = shift or return;
my $path = '/home/mike/www/dev/perl/incluir/';
open INC, "$path/$file" or return $!;
read INC, my $str, -s INC;
close INC;
return $str;
}
## add basic password protection
open PWD, "/home/mike/perl-lib/dbinfo";
my ($user, $pass) = split(/:/, <PWD>, 2);
close PWD;
chomp($user, $pass);
# Connect to DB
my $dbh = DBI->connect('DBI:mysql:basecon', $user, $pass)
or die "Couldn't open database: $DBI::errstr; stopped";
# Prepare SQL query
# this is ordered by 'rating'
my $sth = $dbh->prepare("SELECT * FROM questions ORDER BY rating")
or die "Couldn't prepare statement:$DBI::errstr; stopped";
# Execute the query
$sth->execute() or die "Couldn't execute statement: $DBI::errstr; stopped";
## include files
my $MyWWW = "/dev/perl";
my $imagenes = "$MyWWW/graficos";
my $inc_dtype = include('doctype.inc');
my $inc_head = include('header.inc');
my $inc_intro = include('intro.inc');
my $inc_foot = include('footer.inc');
my $inc_endpg = include('endpg.inc');
# print HTML headers
print "Content-type: text/html\n\n";
## start showing the page
print qq |
$inc_dtype
<title>Linux Knowledge Base </title>
<body bgcolor="#ffffff">
$inc_head
$inc_intro
|;
print "<ul>\n";
# Fetch and print rows from table
while ( my ($how_to, $ID) = $sth->fetchrow_array() )
{
print STDOUT "<li><a href=\"see.pl?ID=$ID\">$how_to</a>\n";
}
print "</ul>\n";
print qq |
$inc_foot
$inc_endpg
|;
# Disconnect
$dbh->disconnect();
|
This script isn't all that different. Instead of submitting information, it
retrieves it. It passes the titles of the how-tos to a bulleted list. This
serves as a link to a script that will show us more detail. Example 14. see.pl #! /usr/bin/perl -w
use strict;
use DBI;
use CGI;
use CGI qw(:standard :netscape :shortcuts);
use CGI::Carp qw(fatalsToBrowser);
# to include files
sub include {
#---------------------------------------------------
# Pass in a file name to include.
my $file = shift or return;
my $path = '/home/mike/www/dev/perl/incluir/';
open INC, "$path/$file" or return $!;
read INC, my $str, -s INC;
close INC;
return $str;
}
## add basic password protection
open PWD, "/home/mike/perl-lib/dbinfo";
my ($user, $pass) = split(/:/, <PWD>, 2);
close PWD;
chomp($user, $pass);
## include files
my $MyWWW = "/dev/perl";
my $imagenes = "$MyWWW/graficos";
my $inc_dtype = include('doctype.inc');
my $inc_head = include('header.inc');
my $inc_intro = include('intro.inc');
my $inc_foot = include('footer.inc');
my $inc_endpg = include('endpg.inc');
# print HTML headers
print "Content-type: text/html\n\n";
# print page
print qq |
$inc_dtype
<title>Linux Knowledge Base</title>
<body bgcolor="#ffffff">
$inc_head
|;
# Connect to the database.
my $dbh = DBI->connect('DBI:mysql:dbname=basecon', $user, $pass);
my $query = new CGI;
my $ID = $query->param('ID');
my $how_to = $query->param('how_to');
my $answer = $query->param('answer');
my $rating = $query->param('rating');
my $sql = "SELECT * FROM questions WHERE ID = $ID;";
my $sth = $dbh->prepare($sql);
$sth->execute();
my $ref = $sth->fetchrow_hashref();
my $rank = $ref->{'rating'};
# this adds points to the database for ranking purposes
my $score = 1;
my $ranking = $rank + $score;
my $sql2 = "UPDATE questions SET rating='$ranking' WHERE ID='$ID';";
$dbh->do($sql2);
# show our data form
print qq |
<p><br>
<p><b>How to: </b>$ref->{'how_to'}
<p><br>
<p><b>Answer: </b><br><i>$ref->{'answer'}</i>
<p><br>
<p align="right"><a href="publist.pl">return to list of how-to</A>
<p><br>
$inc_foot
$inc_endpg
|;
|
This is a slight variation on our previous script. It shows us the
HOW-TO question and the answer. The variation is a routine to
add a point to the ranking every time we view it. This is a little
add-on to get a ranking of how many times somebody looked at this
particular entry. What's left is a means to edit the entries. This script will do the
job. Example 15. edit.pl #! /usr/bin/perl -w
use strict;
use DBI;
use CGI;
use CGI qw(:standard :netscape :shortcuts);
use CGI::Carp qw(fatalsToBrowser);
# to include files
sub include {
#---------------------------------------------------
# Pass in a file name to include.
my $file = shift or return;
my $path = '/home/mike/www/dev/perl/incluir/';
open INC, "$path/$file" or return $!;
read INC, my $str, -s INC;
close INC;
return $str;
}
## add basic password protection
open PWD, "/home/mike/perl-lib/dbinfo";
my ($user, $pass) = split(/:/, <PWD>, 2);
close PWD;
chomp($user, $pass);
## include files
my $MyWWW = "/dev/perl";
my $imagenes = "$MyWWW/graficos";
my $inc_dtype = include('doctype.inc');
my $inc_head = include('header.inc');
my $inc_pie = include('footer.inc');
my $inc_endpg = include('endpg.inc');
# print HTML headers
print "Content-type: text/html\n\n";
# print page
print qq |
$inc_dtype
<title>Linux Knowledge Base</title>
<body bgcolor="#ffffff">
$inc_head
|;
# Connect to the database.
my $dbh = DBI->connect('DBI:mysql:dbname=basecon', $user, $pass);
my $query = new CGI;
my $ID = $query->param('ID');
my $sql = "SELECT * FROM questions WHERE ID = $ID;";
my $sth = $dbh->prepare("$sql");
$sth->execute();
my $ref = $sth->fetchrow_hashref();
# show our data form
print qq |
<form action="update.pl" method="POST">
|;
# entry fields
print qq |
<h2 align="center">Edit HOW-TOs</h2>
<p align="center"><font color="#990000"><b><i>$ref->
{'how_to'}</i></b></font>
<p><br>
<input type="hidden" name="ID" size="2" value="$ref->{'ID'}">
<table align="center" border=0 cellpadding=4 cellspacing=2 width=70%
bgcolor="#foe68c">
<tr><td bgcolor="#FFFACD" colspan="2" align="left" valign="top">
<font COLOR="#990000"><B>How-to: </B></font></td>
<td bgcolor="#FFFACD" colspan="2"><textarea name="how_to" cols="40" rows="4" wrap="virtual">$ref->{'how_to'}</textarea></td></tr>
<tr><td bgcolor="#FFFACD">
<font COLOR="#990000"><B>Difficulty Level: </B></font></td>
<td bgcolor="#FFFACD">
<select name="level">
<option value="$ref->{'level'}">$ref->{'level'}</option>
<option value="NA"> NA</option>
<option value="easy"> easy </option>
<option value="involved"> involved </option>
<option value="difficult"> difficult </option>
<option value="very difficult"> very difficult </option>
</select>
</td>
<td bgcolor="#FFFACD">
<font COLOR="#990000"><B>>Category: </B></font></td>
<td bgcolor="#FFFACD">
<input type="text" name="category" size="50" value="$ref->{'category'}">
</td></tr>
</td></tr>
<tr><td bgcolor="#fffacd" width=50%><font COLOR="#990000">
<B>Importance: </B></font></td>
<td bgcolor="#FFFACD" colspan="3" align="left" valign="top">
<select name="importance">
<option value="$ref->{'importance'}">$ref->{'importance'}</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<BR><font size="3">(We will use this - 1 = a lot, 2 = sometimes 3 = not much)</font>
</td>
<tr><td bgcolor="#FFFACD"><font color="#990000"><B>Keywords: </B></font></td>
<td bgcolor="#FFFACD" colspan="3">
<input type="text" name="keywords" size="70" value="$ref->{'keywords'}">
</td></tr>
<tr><td colspan=4 bgcolor="#FFFACD"><font color="#990000">
<B>Answer: </B></font><BR><textarea name="answer" cols=60 rows=20 wrap="virtual">$ref->{'answer'}</textarea><br>
</td></tr>
<tr><td colspan="2" align="right"><input type="submit"
name="submit" value="OK"></td></tr>
</table>
</form>
<p><br>
$inc_pie
$inc_finpg
|; |
The above script will pass this information on to the next one which will
incorporate or changes into the database. Example 16. update.pl #! /usr/bin/perl -w
use strict;
use DBI;
use CGI;
use CGI qw(:standard :netscape :shortcuts);
use CGI::Carp qw(fatalsToBrowser);
## add basic password protection
open PWD, "/home/mike/perl-lib/dbinfo";
my ($user, $pass) = split(/:/, <PWD>, 2);
close PWD;
chomp($user, $pass);
my $dbh = DBI->connect('DBI:mysql:dbname=basecon', $user, $pass);
my $how_to = param ("how_to");
my $level = param ("level");
my $category = param ("category");
my $answer = param ("answer");
my $keywords = param ("keywords");
my $importance = param ("importance");
my $ID = param ("ID");
# we shouldn't need to touch the rating points
# my $rating = param ("rating");
# to include files
sub include {
#---------------------------------------------------
# Pass in a file name to include.
my $file = shift or return;
my $path = '/home/mike/www/dev/perl/incluir/';
open INC, "$path/$file" or return $!;
read INC, my $str, -s INC;
close INC;
return $str;
}
## include files
my $MyWWW = "/dev/perl";
my $imagenes = "$MyWWW/graficos";
my $inc_dtype = include('doctype.inc');
my $inc_add = include('add.inc');
my $inc_head = include('header.inc');
my $inc_foot = include('foot.inc');
my $inc_endpg = include('endpg.inc');
## print HTML headers
print "Content-type: text/html\n\n";
print qq |
$inc_dtype
<title>Linux Knowledge Base</title>
<body bgcolor="#ffffff">
$inc_cab
|;
if (($answer =~/Microsoft/i) || ($answer =~/Gates/i))
{
print qq |
<b>What are they doing in a Linux knowledge base???</b>
<p><br>
<p>Why don't you try to <a href="edit.pl?ID=$ID">edit this page again</a>
$inc_finpg
|;
}
else {
my $sql = "UPDATE questions SET how_to='$how_to', level='$level',
category='$category', answer='$answer', keywords='$keywords',
importance='$importance' WHERE ID='$ID';";
$dbh->do("$sql");
# Disconnect from the database
$dbh->disconnect;
# print message when we've updated lessons page
print qq |
<p><br>
<table border="0" cellpadding="3" width="98%" bgcolor="#990000" align="center">
<tr><td colspan=2 bgcolor="#fffacd" bgcolor="#ffffff">
<font color="#990000"><u>Question:</u><b>$how_to</b>
</font></td></tr>
<tr><td WIDTH="33%" bgcolor="#ffffff"><u></u>Difficulty Level:</td>
<td bgcolor="#fffacd"> <font color="#990000">$level</font></td>
</tr>
<tr><td WIDTH="33%" bgcolor="#ffffff"><u>Category</u>: </td>
<td bgcolor="#fffacd"><font color="#990000">$category</font></td>
</tr>
<tr><td WIDTH="33%" bgcolor="#ffffff"><u></u>Importance:<br>
<font SIZE="2">(We will use this - 1 = a lot, 2 = sometimes 3 = not much)
</font></td><td bgcolor="#fffacd"><font color="#990000">
$importance</font></td></tr>
<tr><td WIDTH="33%" bgcolor="#ffffff"><u></u>Keywords:<br>
</font></td><td bgcolor="#fffacd"><font color="#990000">
$keywords</font></td></tr>
<tr><td colspan=2 bgcolor="#ffffff"><u>Answer</u>:</td>
</tr>
<tr><td colspan=2 bgcolor="#fffacd">
<font color="#990000"> $answer</font></td></tr>
</table>
<p><br>
<p>If you see things you want to change
<a href="edit.pl?ID=$ID">use this form</a>
<p>Or <a href="add.pl">add another</a>
<p><br>
$inc_foot
$inc_endpg
|;
}
|
We could make the edit scripts more efficient by actually combining them
all into one, but this modular approach is a good way of showing how the
different things work. As with our PHP section, this should serve as
a starting point for Perl web development. If you'd like to improve on
these scripts, there's another homework assignment for you.
|
 |
|