http://qs321.pair.com?node_id=651848

Spidy has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, Fellow Monks.

I am currently working on a project where I am using HTML::Template to populate our template files with the output of our CGI scripts.

Recently, I stumbled accross the fact that you can pass an already opened filehandle in to HTML::Template's new() method.

I had the idea of converting my CGI scripts to store their templates inside themselves - using the __END__ token, like so:

#!/usr/bin/perl -w ## stuff here __END__ <html> <!--template stuff here--> </html>

However, I can't figure out how to actually pass the DATA filehandle to my "Page" module, which is what I'm using to control my templates and output.

The Page module takes a hash of parameters, one of which is the parameter "template". I would like to convert this to be the filehandle that gets passed in to HTML::Template's new() method, but cannot seem to figure out how (Currently, it's the filename that gets passed).

Does anyone know how I would pass the DATA filehandle into my module's constructor function, so that I can use it in a call to HTML::Template->new() within my module?

Thanks,

Spidy



Resolution: As it turns out, HTML::Template has a 'feature' where if you set cache => 1 when you're passing in a filehandle, it does not work.

Replies are listed 'Best First'.
Re: Converting code to use DATA filehandle instead of external templates
by bobf (Monsignor) on Nov 20, 2007 at 05:02 UTC

    I'm a little confused. You talk about using __END__ but then you mention passing the DATA filehandle. I assume you meant to use __DATA__ instead.

    HTML::Template's new() method can also take text as the template, it doesn't have to be a filehandle. Per the docs:

    Alternately you can use:
    my $t = HTML::Template->new( scalarref => $ref_to_template_text, option => 'value' );
    and
    my $t = HTML::Template->new( arrayref => $ref_to_array_of_lines , option => 'value' );
    These initialize the template from in-memory resources.

    It looks like you can just slurp in your template (using while( my $line = __DATA__ ) or similar) and then pass the string to HTML::Template->new().

Re: Converting code to use DATA filehandle instead of external templates
by snoopy (Curate) on Nov 20, 2007 at 06:29 UTC
    You just need to setup a DATA block and pass through filehandle => *DATA to HTML::Template
    #!/usr/bin/perl use warnings; use strict; use HTML::Template; #------------ package Page; use base 'HTML::Template'; sub new { my $self = shift; my %args = @_; $self->SUPER::new(%args); } #------------ package main; my $template = Page->new(filehandle => *DATA) || die "Unable to open template"; $template->param(orb => 'world'); print $template->output; __DATA__ hello <TMPL_VAR orb>
Re: Converting code to use DATA filehandle instead of external templates
by naikonta (Curate) on Nov 20, 2007 at 06:29 UTC
    (Update, per haoess below) First of all, the DATA filehandle begins after the __DATA__ token, not __END__. Here's one example to do it.
    $ cat /tmp/html-data.pl #!/usr/bin/perl use strict; use warnings; use HTML::Template; use File::Basename; my($script, $path) = fileparse($0); # the use of load_page() is intentional my $template = load_page(\*DATA); $template->param( script => $script, path => $path, pid => $$, ); print $template->output; sub load_page { my $fh = shift; HTML::Template->new(filehandle => $fh); } __DATA__ Hi, I'm script <tmpl_var name=script>, located at <tmpl_var name=path> running with process id <tmpl_var name=pid> $ perl /tmp/html-data.pl Hi, I'm script html-data.pl, located at /tmp/ running with process id 4291
    Actually, you can also use the scalarref or arrayref options with DATA, such as,
    my $template = load_page([<DATA>]); sub load_page { my $stuff = shift; HTML::Template->new(arrayref => $stuff); }
    Or,
    local $/ = undef; my $template = load_page(\<DATA>); sub load_page { my $stuff = shift; HTML::Template->new(scalarref => $stuff); }

    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

      First of all, the DATA filehandle begins after the __DATA__ token, not __END__
      That's not always correct. perldoc perldata says:
      __END__ behaves like __DATA__ in the toplevel script (but not in files loaded with "require" or "do") and leaves the remaining contents of the file accessible via "main::DATA".
      $ cat data_eq_end.pl #!/usr/bin/perl use warnings; use strict; print for <DATA>; __END__ 1 2 3 $ perl data_eq_end.pl 1 2 3

      -- Frank

Re: Converting code to use DATA filehandle instead of external templates
by GertMT (Hermit) on Nov 20, 2007 at 06:33 UTC
    A post that shows how it worked for me except that the use of HTML::Template isn't how it should be as described in the comments. creating HTML table