A few years ago I posted a message asking for the Perl Monks to critique my style (A Matter of Style in CGI). I received several responses that helped me to improve my Perl coding. Well, now I'd like to do that again. In those days I did only very simple CGI scripts, drawing data from MySQL. I still do plenty of CGI scripts displaying data from MySQL, but much more involved than before, as well as other things. I'd like to get some critiques again on my coding style related to CGI and MySQL and in a few other areas. I would love to post many pages of code to get feedback. However, to start, I'll stick to something similar to the last time: a script using CGI and DBI.
Below is a CGI Perl script on my personal web site which has a couple of uses—go to it if you want to see the results of this script. If the user provides no parameters, it will list the last ten of my musings (i.e., web log entries) stored in a table in MySQL. If the user provides a category (e.g., italian), it will give all musings from that category (e.g., all musings on learning Italian). If the user presents an identification number for a specific musing, the user is redirected to a different script.
#!/usr/bin/perl -w
use strict;
# Program Name: musings.cgi
# Description of Program:
# This is a Perl script which creates the page
# for viewing a list of my web log entries.
# set libraries, scripts, & paths
require './library/main.pl';
require './library/musings.pl';
my $scripts = &get_script_variables(); # main.pl
# capture user input
my $musing_id = param('musing_id') || '';
my $ref_id = param('ref_id') || ''; # musing category
# reroute user to musing if given an id
if($musing_id =~ m|\d|g) {
print redirect($scripts->{'musing'}->{'script'}
. '?musing_id=' . $musing_id);
exit;
}
if(!$ref_id) { # if no category requested,
$ref_id = 'all'; # select all categories
}
# get web log entries and related info from MySQL
my $entries = &get_musings_entries($musing_id,$ref_id); # musings.pl
my $comment_cnt = &get_comments_count(); # musings.pl
my $musing_stats = &get_reader_stats(); # musings.pls
my $musing_cats = &get_musings_categories(); # musings.pls
# get general text for web page from MySQL
my $genl_text = &get_general_text('musings',1); # center.pl
my ($pg_head,$pg_text,$pg_image) = @{$genl_text->[0]};
my $n = "\015\012";
# start web page
&heading('musing',undef,$pg_head,undef,$pg_text); # header.pl
# left margin
&panel_start(1); # main.pl
&fiction(); # left_margin.pl
&miscellany(); # left_margin.pl
&musings_sites(); # left_margin.pl
&panel_end(); # main.pl
# center panel of web page
&panel_start(2); # main.pl
# display page heading
print start_div({id=>'page_heading'}), $n;
if($musing_id =~ /[a-z]/ && $musing_id ne 'all') {
my $cat_head = ucfirst($musing_cats->{$musing_id}->{'ref_name'});
$pg_head = $cat_head . $pg_head;
my $sub_genl_text = &get_general_text('musing_cat',1); # center.pl
my ($sub_pg_head,$sub_pg_text) = @{$sub_genl_text->[0]};
$pg_text = $sub_pg_text;
&page_heading($pg_head,$pg_text,undef); # center.pl
}
else {
&page_heading($pg_head,$pg_text,undef); # center.pl
}
print end_div(), $n,$n; # end div#page_heading
# display web log entries
foreach (@$entries) {
my ($entry_id, $ref_id, $log_head, $entry, $entry_date) = @$_;
my $category = lc($musing_cats->{$ref_id}->{'ref_name'});
my $count = $comment_cnt->{$entry_id}->{'comment_cnt'} || 'no';
my $reader_stat = $musing_stats->{$entry_id}->{'stat'};
$entry_date = lc($entry_date);
print div({class=>'content_item'}, $n,
div({class=>'musing_abstract'}, $n,
h3( a({href=>$scripts->{'musing'}->{'script'}
. '?musing_id=' . $entry_id},
$log_head) ), $n,
span($entry), $n ), $n,
div({class=>'item_stats'}, $n,
qq|posted: $entry_date ; readers: $reader_stat |, $n,
a({id=>'comment_notation',
href=>$scripts->{'musing'}->{'script'}
. '?musing_id=' . $entry_id},
$count, 'comments; '), $n,
'category: ',
a({id=>'comment_notation',
href=>$scripts->{'musings'}->{'script'}
. '?ref_id=' . $ref_id},
$category) ), $n ), $n,$n;
}
&panel_end(); # main.pl
# right margin
&panel_start(3); # main.pl
&display_page_image($pg_image); # right_margin.pl
&get_display_category_data(); # musings.pl
&stats_musings(); # right_margin.pl
&panel_end(); # main.pl
&footer(); # main.pl
exit;
I added some hard-returns above to items such as a({href=>''} so that the lines wouldn't wrap here, to make it easier to read. You'll notice also that there are references to functions contained in several libraries. I don't want to wear y'all out by posting all of my libraries. However, I've included one function, &get_musings_entries() from my musings.pl library. In another post I might include a sampling of some key functions I've created, but for now I'll settle for this one. This function queries the MySQL database, with the SQL statement set based on whether the user has provided a musing category, has requested all categories, or has provided an identification number for a specific musing. Incidentally, the connection to MySQL is established by a different function elsewhere.
sub get_musings_entries {
# get musings from MySQL
my ($musing_id,$ref_id) = @_;
if($ref_id && $ref_id eq 'all') {
$sql_stmnt = qq|SELECT musing_id, ref_id,
heading,abstract,
DATE_FORMAT(entry_date, '%M %e, %Y')
FROM musings
ORDER BY entry_date DESC|;
}
elsif($ref_id) {
$sql_stmnt = qq|SELECT musing_id, ref_id,
heading, abstract,
DATE_FORMAT(entry_date, '%M %e, %Y')
FROM musings
WHERE ref_id = '$ref_id'
ORDER BY entry_date DESC
LIMIT 10|;
}
else {
$sql_stmnt = qq|SELECT musing_id, ref_id,
heading, entry,
DATE_FORMAT(entry_date, '%M %e, %Y')
FROM musings
WHERE musing_id = '$musing_id'|;
}
$sth = $dbh->prepare($sql_stmnt);
$sth->execute();
my $entries = $dbh->selectall_arrayref($sql_stmnt);
$sth->finish();
return $entries;
}
As I said in my post several years ago, I'd like all of the criticisms that I can get. However, please don't feel obligated to review and comment on everything. You could just pick out one line that stands out. Whatever you have time to do is appreciated. I would like comments on functionality, documentation, layout, spacing, etc. No criticism will be considered too minor. Thanks again in advance.
-Spenser
That's Spenser, with an "s" like the detective.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.