The very first step is to import the WACS API modules into your program file along with those standard modules needed to access the database. These files should be in the right location already and should just be found without any additional specification of where they are.
The same code segment implemented in perl looks like:
use Wacs; use DBI;
Note | |
---|---|
The PHP interface requires an Object Handle
to use when accessing the WACS module which we're simply calling
|
The second step is to read the standard WACS configuration file to find out where everything is, and then check that this user is allowed to access the WACS system. This is a two step process, and the reading of the configuration file must be done first; otherwise WACS doesn't know where to look for the security files it needs to determine whether this user should be given access or not.
Example 2.2. Config and Security
// read the Wacs configuration files $wacs->read_conf(); // check the auth(entication and authorisation) of this user $wacs->check_auth( $_SERVER['REMOTE_ADDR'], 1 );
and here is the same thing again in the perl dialect:
# read the Wacs configuration files read_conf; # check the auth(entication and authorisation) of this user check_auth( $ENV{"REMOTE_ADDR"}, 1 );
The third step is to initialise the database connection. Since some databases require an environment variable to determine where their configuration files have been stored, this needs to be set first. Wacs provides for this and this code will create that environment variable, if needed, and then proceed to establish the database connection itself.
Example 2.3. Database Connection Initialisation
// database initialisation // - establish environment variable $dbienv = $wacs->conf_get_attr("database","dbienvvar"); if( ! empty( $dbienv )) { putenv($dbienv."=".$wacs->conf_get_attr("database","dbienvvalue")); } // - connect to the database $dbhandle= DB::connect( $wacs->conf_get_attr("database","phpdbconnect") ); if( DB::iserror($dbhandle)) { die("Can't connect to database\nReason:".$dbhandle->getMessage."\n"); } $dbhandle->setFetchMode(DB_FETCHMODE_ORDERED);
and here's how we do it in perl:
# database initialisation # - establish environment variable $dbienv = conf_get_attr( "database","dbienvvar" ); if( $dbienv ne "" ) { $ENV{$dbienv}= conf_get_attr( "database","dbienvvalue" ); } # - connect to the database $dbhandle=DBI->connect( conf_get_attr("database","dbiconnect"), conf_get_attr("database","dbuser"), conf_get_attr("database","dbpass") ) || die("Can't connect to database\nReason given was $DBI::errstr\n");
OK, let's just study this code for a moment. It first calls the
WACS API function conf_get_attr with the section
parameter of database as it wants database related
configuration information, and an argument of dbienvvar.
The WACS API function conf_get_attr is short for
configuration get attribute and returns the value of the
configuration file parameter of that name or it's default value. The
dbienvvar
means database interface environment
variable.
A typical value for this might be something like ORACLE_HOME
which is the environment variable that Oracle 10g and 11i requires
to be set in order to find it's current configuration.
The next line of the code checks to see if we got back an actual
variable name (eg ORACLE_HOME
) or an empty string (ie
nothing). If we were given a valid variable name, then we're going to need
to set it the value it should be, which again we can get from the configuration
file, this time called dbienvvalue
which is short for
database interface environment value (as distinct from
the variable name we just looked up). A likely value
for this might be /usr/local/oracle
. Obviously if we're
given no variable name to set, there's no point looking for a value for it!
Conversely we are assuming that having bothered to name the variable in the
configuration file, also put in a valid value for it - this code could break
if the variable name is specified but not it's value.
The second section of these code segments is to do with the
establishment of a connection to the database and is a little different
between the two versions. Both systems use a handle for the database
connection, which we call $dbhandle
- imaginative name
huh? In both cases, the respective database APIs provide a
connect function which takes an argument of how to connect to
the database. The Php version takes a single argument, which is stored
in our configuration files as phpdbconnect
and
includes the whole username, password and database specification in a
single lump. The Perl version asks for three: the database specification,
the username and finally the password. The configuration file knows these
as dbiconnect
, dbuser
and
dbpass
respectively.
The final bit copes with putting out some kind of error message, at least showing the point of failure, if we are unable to establish a connection to the database. The methods are very slightly different, but the effect is very much the same between the two versions. We then just tell the PHP DB interface how we wish it to organise the returned data; the perl DBI default is pre-determined and is what we want.
Tip | |
---|---|
Note that you might wish to have completed the output of the HTML header section and started the body by this point so that should the database connection fail, the error message will be visible. |
The next step in the process is to use the database connection we've established to actually make a request of the database. For now don't worry about what that request is or how we've written it - we'll come back to that topic in detail later in this chapter. Look at the mechanics of how we're issuing the request and getting back the results. What we're going to ask the database for is a list of those girls who are marked as Favourite Solo models. We chose this because both the models in our current samples directory are marked as this and so even if you only have our sample records loaded, you should find some matches.
Example 2.4. Database Query
// do db select // 0 1 2 3 $query = "select mname, modelno, mbigimage, mimage from ". $wacs->conf_get_attr("tables","models"). " where mflag = 'S' order by mname"; $cursor = $dbhandle->query( $query );
The method is a little different in perl in that it is seperated into two steps; as a result it looks like this...
# do db select # 0 1 2 3 $query = "select mname, modelno, mbigimage, mimage from ". conf_get_attr("tables","models"). " where mflag = 'S' order by mname"; $cursor = $dbhandle->prepare( $query ); $cursor->execute;
Note | |
---|---|
The query structure is very similar between Php and perl apart for the two step process of validating and then seperately executing the query in perl. This is mostly down to different traditions that exist for database accesses in each language. The net result is similar in technical terms and identical in output terms |
In both cases we're putting together an SQL query that reads:
select mname, modelno, mbigimage, mimage from models where mflag = 'S' order by mname
This query asks the database to fetch the four named items:
mname, modelno, mbigimage,
and mimage
from the database table called models
where the field mflag
has a value of the capital letter
S
and to sort the results it returns to us by the value
in the field called mname
. It may not surprise you to
learn that mname
is the model's name, modelno
is our reference number for her, mbigimage
is the (location of the) large size headshot of her and mimage
is the (location of the) smaller size headshot of her.
You may have noticed that the only part of this that wasn't copied
verbatim from the code is the from models
bit and that
there we've used the WACS API call conf_get_attr to
get the actual name of the database table concerned from the main WACS
configuration file. This is actually important and it's strongly
recommended that you do use this form when creating SQL queries. If you
really insist on knowing why, take a look at the section on the tables
part of the wacs.cfg configuration file in the WACS configuration guide.
Once we've created the SQL query, we feed it to the database routines.
The first step is to pass in the SQL query and have the database perform
that search on the database. Once the query has been executed, we want
to pull back the matching records (or rows
in database
parlence) for each model.
In both Php and Perl we're calling a routine that returns to us a single
row from the database (a single model's record in this case) each time it's
called. When we run out of records, a null return is given and our while
loop ends.
In Php, the function to do this is called using fetchRow
which returns the next row as an array of values, which we assign into the
variable $results
each time.
In Perl, the function we're using is called fetchrow_array
because perl offers us a choice in the type of data we are returned and
in this case we want a numerically indexed array.
Note | |
---|---|
There are other approaches to getting back the data, including
having it returned in one big lump (such as with the Php call
|
The final step is to actually generate some output from the data we've fetched from the database. We're going to do this as an unordered list in HTML, so we're going to be adding a little formating to the output as we retrieve each record.
Example 2.5. Outputing The List
print "<ul>\n"; while( $results = $cursor->fetchRow() ) { print "<li>"; print "<a href=\"".$wacs->conf_get_attr("server","cgiurl"); print "wacsmpthumbs/".$results[1]."\">"; print $results[0]."</a></li>\n"; } print "</ul>\n";
and here's the perl version...
print "<ul>\n"; while( @results = $cursor->fetchrow_array ) { print "<li>"; print "<a href=\"".conf_get_attr("server","cgiurl"); print "wacsmpthumbs/".$results[1]."\">"; print $results[0]."</a></li>\n"; } print "<ul>\n";
We start off by printing out the HTML instruction to start an
unordered list (<ul>) in a line on it's own. We then start a
while loop which goes through each entry until it's done them all.
Both versions use the database cursor object ($cursor
)
to fetch the next record (aka row) from the database using the
fetchRow or fetchrow_array method
and assigning it into the array $results
(or in perl
@results
). The act of the assignment fails
when there are no more records to fetch and the while loop will terminate.
The construct here is based upon the fact that both languages have seperate
operators for assignment (=
) and comparison
(==
and eq
) and so the code is
unambiguous (at least to the php and perl interpreters it is!).
Once inside the body of the while loop we print out the start of list
entry tag (<li>
) and start in on making use of the
data. In the quest to make this example a little bit more satisfying, we've
tried to make sure this application does something vaguely useful. A simple
list of names is all well and good, but we wanted it to actually
do something! So what we've done here is to
create a link around each models name that points to her model page as
displayed by the standard WACS tools. The raw HTML to achieve this would
look like:
<a href="http://www.mywacsserver.com/cgi-bin/wacsmpthumbs/123"> Sarah</a>
So we're left with a slight problem here in that we don't know in advance (trust me on this) what the WACS server is called, we don't know what the models are called and we don't know what their numbers are. We have no idea if we have a model number 123 or not and whether she's called Sarah; but the WACS system should be able to fill in all the blanks for us.
The first part of the code merely prints out the start of the
HTML <a href=">
and then we ask the WACS configuration
system what it's externally visible URL for cgi-bin programs is. We do this
using the conf_get_attr call again, telling it we want an
answer in the section server of the URL for cgi
scripts aka cgiurl
. On the next line of the example
we put the name of the WACS application we want to link to, in this case
wacsmpthumbs. Since the way we tell
wacsmpthumbs what we want it to look up is to add a slash and
then the model number to the URL, we add a slash (/
) on
the end and then the number.
Tip | |
---|---|
You may have noticed that we added a comment on the line above the SQL select statement with 0,1,2,3 with each number above the field name in the query. This was a shorthand to ourselves to remind us what the index number in the array is for each of those database fields. |
Since the order of the fields we asked for was mname, modelno,
mbigimage
and then mimage
, the results in the
array will be the same - element 0 will be the mname, element 1 will be the
model number, and so on. In both cases we're dealing with a single-dimensional
array. The first field we want to go into the URL for
wacsmodelthumbs is the model number, so that
will be element 1 (not zero) therefore we write $results[1]
.
We then finish off the URL reference by closing the quotes (") and the
>
tag.
We then want to print the model's name which will be element 0 in our arrays, put out the closing anchor tag (</a>) and then finish off the unordered line entry with the end line tag (</li>). We then print out a new line so the generated page is easier to read. The moving on to the next record will be done as a by-product of the test for the next iteration around the while loop. Once we exit the loop, we finish off the HTML unordered list.
To just finally finish it off, we need to add a few more pieces just
to make it work. For the Php version, we need to declare it as being a
php program with <?php
at the very start of the file,
with a matching ?>
at the very end. For perl, we
need to declare it as a perl script with the very first line being just
#!/usr/bin/perl
. Additionally for perl, we need
to output the mime content type declaration so that the web browser knows
what kind of object it's being passed - this is done simply with:
print "Content-Type: text/html\n"; print "\n";
Next we need a couple of lines of HTML preamble near the beginning (as mentioned before, just before the database connection code so we could see any error message that appears):
<html> <head> <title>MySimple: Index Of Favourites</title> </head> <body>
Similarly at the end, we just need to finish the page off with the html tail piece:
</body> </html>