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;
Tip | |
---|---|
The PHP interface requires an Object Handle
to use when accessing the WACS module which we're simply calling
|
You will note that in Perl we import a database abstraction library called DBI that allows us to make connections to and ask questions of an external relational database. In Php there is a very similar system available called PDO (Php Data Objects) but it is normally included by default and is installed as a part of the language itself using the extensions mechanism.
Note | |
---|---|
In past times, we used to use an external module called DB.php but this had become unreliable and we have re-written all the code to use PDO. You might still find occasional examples that reference it. |
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 try { $dbhandle= new PDO( $wacs->conf_get_attr("database","phppdoconnect"), $wacs->conf_get_attr("database","dbuser"), $wacs->conf_get_attr("database","dbpass") ); } catch( PDOException $e ) { die("Can't connect to database\nReason:".$e->getMessage."\n"); }
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 way to open
the connection to the database and return us the handle we will use for
future actions. In the Php case, we create a new object
of type PDO with the necessary three parameters to make the connection.
In Perl we simply call the DBI connect function with those
same three pieces of information.
These three pieces are: the database specification, the username and
finally the password. The configuration file knows these as
phppdoconnect
or 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.
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. We will show you how to present the error to the user in a better way later on. |
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 all three of 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->prepare( $query ); $cursor->execute();
And the perl version pretty much the same:
# 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;
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 fetch
which returns the next row in the way we request. Here we ask for it to be
returned to us as an array of values by specifying PDO::FETCH_NUM
. We assign this array of values into the variable
$results
each time.
In Perl, the function we're using is called fetchrow_array
because perl gives us the choice of how we want the data returned to us in
the name of the function. There are other function names in perl that provide
other layouts of the data - a PDO::FETCH_ASSOC
argument to
fetch in php is much the same as using
fetchrow_hashref
in perl.
Note | |
---|---|
There are other approaches to getting back the data, including having it returned in one big lump - this has been avoided as some WACS installations have tens of thousands of matching records for some queries. It is good practice and perfectly OK to handle one record at a time and the database routines can cope well with this. |
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->fetch(PDO::FETCH_NUM) ) { 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
fetch(PDO::FETCH_NUM) 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>