[prog] perl woes...

Jacinta Richardson jarich at perltraining.com.au
Sun Jun 1 12:17:47 EST 2003


On Sat, 31 May 2003, Patricia Fraser wrote:

G'day Patricia,

> I'm wading through my project from the middle outwards, and trying to 
> learn Perl as I go, so hopefully these questions aren't too muddy. I'm 
> working on a CGI app that uses a MySQL database, Perl CGI scripts, 
> Apache; the idea is for users to make selections from drop-down lists 
> where there's data in tables, and then fill in form fields, and for the 
> results of the lot to get written back to the database.

Sounds good.  You may find our course notes at
http://www.perltraining.com.au/notes.html of some use in this work.  Feel
free to download and read and share with your friends.  Feedback would be
very much appreciated.

> First, I don't understand what's happening in a statement like 
> 
> $tmpl->param( supplist => \@suppliers );

Here I'm assuming that $tmpl is your object reference from the
HTML::Template class.  Since $tmpl has been blessed into this class we can
call any HTML::Template method on it that we know about.  (The -> allows
us to call that method on our $tmpl object reference.  Strictly speaking ->
allows us to dereference any reference.  So we can access values in an
array reference by doing:
	my @array = qw/one two three/;
	my $arrayref = \@array;
	print $arrayref->[0];  # prints "one"
and if our underlying structure is a hash, we can access object
internals by doing 
	$tmpl->{cgi} 
although you really shouldn't do that - data encapsulation and all).

The param method in HTML::Template allows us to pass information to the
template as to what we wish to replace the TMPL_* tags with.

In this case we're passing a list reference into param.  The call could
also have been written:
	$tmpl->param( "supplist", \@suppliers );

or
	my $suppliers = \@suppliers;
	$tmpl->param("supplist", $suppliers);

or
	my %params = (supplist => \@suppliers);
	$tmpl->param(%params);
	
or something like

	my $suppliers = [ 
			  { 
			    name => "Some place",
                            product => "Some product",
			    price => "$12.34"
			  },
			  {
			    name => "Bill's stuff",
			    product => "Apples",
			    price => "$1.20 / kg"
			  }
			];
	$tmpl->param( supplist => \@suppliers );

and the matching html template code would look similar to:
<!-- TMPL_LOOP name="supplist" -->
 	<tr>
	<td>
	<p><!-- TMPL_VAR name="name" --></p>
	</td>
	<td>
	<p><!-- TMPL_VAR name="product" --></p>
	</td>
	<td>
	<p><!-- TMPL_VAR name="price" --></p>
	</td>
	</tr>
<!-- /TMPL_LOOP -->


	=> is pronounced "fat comma" in Perl.  It's syntatically the
same as "," except that Perl assumes that you intended the quote the
single last word to the left of the comma if it's currently a bareword.
It's used in creating hashes or associated lists because it makes it
very easy to pair items mentally, whereas commas don't.  Note that
there's nothing strictly wrong with:

my @list = (fish => and => chips => and => "vinegar");

although I hope that the person who maintains scripts with such in them
comes back to haunt you.

	\@array takes a reference to that array.  All references in Perl
are scalars which allows you to build up quite complex data structures,
similar to what I did with $suppliers up above.  Had we written:

	$tmpl->param( supplist => @suppliers );

then HTML::Template would have a hard time working out whether we were
assigning many things in the call to params (because param allows you to
assign many things at once, for example:

	$tmpl->param( supplist => \@suppliers,
	              fish => 1,
		      title => "This is a good place" );

) or whether all but the first thing in the list should be in an array
reference.

Let me know if you have any more questions about this.

> I guess there are a couple of things I don't understand; first, Vwhat 
> "=>" does as opposed to what "->" does, but more to the point, what's 
> actually happening when I'm tracking back through references (which 
> I've figured out are actually memory addresses) to get back the stored 
> value, which is what I want.

As you've said, references are memory addresses in Perl.  When you
dereference a reference (track back through it) you get either the
underlying structure, or access to it.  For example:
	print $fish->[0];
will print out the zeroth element of the array pointed to by the $fish
scalar.  Whereas:
	print @{$fish};
will result in printing the entire array out, effectively returning the
full underlying structure.

> I'm also hoping for help with pointers to working out what 
> templating system (if any) might be most helpful. I've read pretty much 
> everything I can find, but some light-bulb moments would be lovely! 
> 
> I chose HTML::Template because of the looping thing, for populating 
> drop-down lists, 

I almost always use HTML::Template when doing CGI stuff.  It's easy,
efficient and works very very well with CGI.pm.  For non-CGI stuff,
Template::Toolkit is hard to pass up.

> but it seems to have a drawback - I'd like the choices 
> the user makes in the first two lists to be able to be plugged into the 
> select statement for the third list, so the third list will only have 
> data according to the first two choices. 
> 
> Seems like, once having decided to template at all, I have to move to a 
> new page to display the third list, because I can't get the template to 
> update the third list after the choices are made - ! I can update a 
> page if I use a here-document, but that doesn't seem to allow me to 
> populate the lists from the database. Grr!

Unfortunately you've encounted one of the big problems with server side
scripting.  When you generate the page (whether using a template or
using a heredoc, or any other method) you must generate it _in_full_
before sending it to to the client.  Once the client has it, THEN they
can make selections from the menus, write in the text boxes and so on.
Unfortunately, you cannot make the client tell you what they've done
without them submitting their page and you can't send them more
information unless they request it (usually again byt submitting their
page).

This is usually solved by using some sort of client-side scripting as
well - the most common by far being Javascript.  It is possible to allow
Javascript to connect back to the server and request database
information to populate the third pull-down but it isn't nice and easy.

By the way, Javascript can be great for client-side validation, but
don't ever forget that the server must do it's own validation too.  It's
very easy to get around javascript validation and collecting corrupt
data is less than useful.

> I've got a thing working, with the extra-page way, but it seems a bit 
> inelegant, and I'd really like to find out a solution to the problem 
> anyway, because I'll need it again later...

Either learn Javascript, or redesign your page, are the only two ways
I've solved this in the last 6 years of trying.

> There are more questions, but this is more than enough for now!

Ask away.  I hope these help.

		Jacinta

--
   ("`-''-/").___..--''"`-._          |  Jacinta Richardson	    |
    `6_ 6  )   `-.  (     ).`-.__.`)  |  Perl Training Australia    |
    (_Y_.)'  ._   )  `._ `. ``-..-'   |      +613 9354 6001 	    |  
  _..`--'_..-_/  /--'_.' ,'           | contact at perltraining.com.au |
(il),-''  (li),'  ((!.-'              |   www.perltraining.com.au   |



More information about the Programming mailing list