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

I have a number of CGI scripts I need to get within my new website template. Some of them have header/footer files and some do not.

Normally this would be an easy task but as it is, my site has 6 separate SSIs for each page (the main page, header, footer, table1, table2, etc). How can I get my scripts to working within my layout if I have so many server side included files per page?

My first idea was to drop the 6 SSI's and make them into just 2 somehow and use them normally as a header/footer for the CGI scripts. I really don't think having to create tons of different templates with different included files is the route I want to take.

The only other idea I had would be to use LWP::Simple to open my site like a browser would see it (a full page with all the SSI content already nested inside) and then break it apart into 2 files (a header and a footer file). This would work on the fly and would change as often as the script is loaded and I would never have to create more server side includes to make it work. I would have to find a way to include an HTML comment for the script to separe the header and the footer from.

Right now, I think the last idea would be the best. I'm not even sure if it's possible, so any suggestions or ideas you can offer would be much appreciated.

Thanks.

Replies are listed 'Best First'.
Re: CGI within your layout
by Tanktalus (Canon) on Jan 17, 2005 at 17:24 UTC

    There may be more than one way to do it, but there's also more than one way to think about (doing) it.

    sub display_template { my %opts = @_; my $output; my $files = $opts{file}; my @files = ref $files ? @$files : ($files); unless ($opts{no_header} or $opts{bare}) { my $header = $opts{header} || 'header.tmpl'; my $tmpl = HTML::Template->new($header); $tmpl->param(...); # common params $tmpl->param(%{$opts{header_param}}) if $opts{header_param}; $output .= $tmpl->output(); } foreach my $file (@files) { my $tmpl = HTML::Template->new($file); $tmpl->param(...); # common params $tmpl->param(%{$opts{params}}) if $opts{params}; $output .= $tmpl->output(); } unless ($opts{no_footer} or $opts{bare}) { my $footer = $opts{footer} || 'footer.tmpl'; my $tmpl = HTML::Template->new($footer); $tmpl->param(...); # common params $tmpl->param(%{$opts{footer_param}}) if $opts{footer_param}; $output .= $tmpl->output(); } $output; }

    That's pretty close to what I use for mine. As you can see, it takes named parameters - things like "file" which can take either a single file name, or an arrayref of filenames, or 'header' to name the header file (defaults to 'header.tmpl'), or 'no_header' to remove the header altogether, or 'bare' to remove both header and footer at the same time. Then there's 'header_param' which is a hashref of parameters to pass in to HTML::Template for the header, similarly for the main files and the footer. And then, it returns the whole thing - because I use CGI::Application, and that's the way C::A works.

    Hope that helps.

Re: CGI within your layout
by perrin (Chancellor) on Jan 17, 2005 at 18:03 UTC
    There are several SSI modules on CPAN that will simulate SSI for your CGI scripts. Look at CGI::SSI or CGI::SSI_Parser for starters.
Re: CGI within your layout
by cfreak (Chaplain) on Jan 17, 2005 at 19:39 UTC

    Well as others have stated using some kind of SSI parser within CGI would probably get you where you're going, however I don't feel this is the best way.

    In my opinion the best way is to turn your logic around. Instead of trying to include your CGIs in a layout, include your layout in your CGIs with a templating system such as HTML::Template. Tanktalus seems to be doing that in his example, though I would use the templating engine's logic rather than his method of including certain things.

    If you need to keep your links the same (since in my method you would call a CGI script directly rather than an HTML file) I would simply use the URL rewritting features of Apache to get people to the correct link.

    HTH

Re: CGI within your layout
by Anonymous Monk on Jan 17, 2005 at 20:10 UTC
    Just for now anyway I think I will try my second idea, just to see if it works as I plan. Can anyone give me a snippet to read from $content the top section and bottom section (both being stored in $1 and $2) that's separated by
    <!-- SCRIPT TEMPLATE BREAKS HERE -->
    ?

    I need everything above that line stored as $1, everything below as $2.

    My best attempt would be

    use LWP::Simple; my $content = get("http://www.url.com/scripttemplate.shtml"); my $breakline = "<!-- SCRIPT TEMPLATE BREAKS HERE -->"; while ($content) { $content =~ /(.*)$breakline(.*)/); }