Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Framing my scripts

by Spidy (Chaplain)
on Jul 26, 2007 at 22:53 UTC ( #629020=perlquestion: print w/ replies, xml ) Need Help??
Spidy has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, fellow monks.

I am currently working on a project that involves having a number of pages that all have the same basic 'frame':

#!/usr/bin/perl -w use DBI; use strict; use CGI; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); use HTML::Template; use HTML::Entities; use lib 'code'; use config; my $template = templates::loadTemplate('template'); my %T; my $innerTemplate; ## Security $CGI::DISABLE_UPLOADS = 1; # no uploads! $CGI::POST_MAX = 512*1024; # max 512k post my $q = new CGI; my $c; ## different stuff here ## Filling in the template here if($innerTemplate) { # load the template in, put it into %T. my $template = templates::loadTemplate('$innerTemplate'); $template->param($T{innerContent}) if $T{innerContent}; $T{content} = $template->output(); } print $q->header(); $template->param(%T); print $template->output();

...And the only thing that seems to differ from script-to-script is the area that says "different stuff here".

This has gotten me to wondering: is there a way that I could write my scripts so that I would only need to write my 'frame' once? The code for a specific script would then somehow just get included into the area it needed to be. Does anyone know if this is possible, and how I'd do it if it was?

Thanks,

Spidy

Comment on Framing my scripts
Download Code
Re: Framing my scripts
by grep (Monsignor) on Jul 26, 2007 at 23:24 UTC
    Check out the TMPL_INCLUDE tag.

    This should give you several ways to handle a framing template. You could have an outer template then specify the inner or add a header and footer to each template. Both work well it just depends on your situation.

Re: Framing my scripts
by Cody Pendant (Prior) on Jul 27, 2007 at 00:45 UTC
    The way I read your question you're not talking about varying what goes into your HTML Template, you're talking about varying what goes into your script?

    As this is clearly a CGI script, couldn't you just use a parameter and do

    if{$q->param('mode' eq 'foo')}{ # do some stuff } if{$q->param('mode' eq 'bar')}{ # do some other stuff }
    which would mean you just had one big script?

    If you don't like that, why not

    if($mode eq 'foo'){ require 'foo.pl'; }
    which will leave you one small script which calls others as required?

    You could even do this:

    require "$mode.pl";
    But it's got "security hole" written all over it.


    Nobody says perl looks like line-noise any more
    kids today don't know what line-noise IS ...
Re: Framing my scripts
by dsheroh (Parson) on Jul 27, 2007 at 02:15 UTC
    I typically handle that sort of thing with an 'action' parameter on the CGI request and a dispatch table to call the corresponding code:
    my $default_action = 'dothis'; my %actions = ( dothis => \&do_this, dothat => \&do_that, dosomethingelse => \&do_something_else, ); my $action = param('action'); $action = $default{action} unless defined $actions{$action}; &{$actions{$action}}();
Re: Framing my scripts
by kyle (Abbot) on Jul 27, 2007 at 02:21 UTC

    If you're not afraid of objects, you can put the "wrapper" stuff in a base class which calls different_stuff(), which is always overridden by a subclass. You can then break up the wrapper stuff into various pieces, and the subclasses can override any other parts they like. Then an individual script would instantiate the subclass and invoke some main() or something.

    Otherwise, you might take the wrapper stuff and stick it in a module that your individual scripts use. They can pass in a code ref to their own functionality. It might look like this:

    use My::Wrapper qw(wrap); sub hello_world { my %params = %{shift()}; my $q = $params{q}; # etc. # different stuff here } wrap( \&hello_world );

    Inside wrap...

    sub wrap { my ( $code_ref ) = @_; # blah blah $code_ref->({ q => $q, T => \%T, # etc. }); # blah blah }

      This looks like a really cool way to do what I'm looking for, except...I don't quite understand it.

      Let's say I have 2 scripts I want to implement this way; one will print "Hello World", and the other will print "Foo Bar". How would I set that up using your method?

      Thanks,

      Spidy

        In "Hello World":

        use My::Wrapper qw( wrap ); wrap( \&hello_world ); sub hello_world { my %params = %{shift()}; my $T_ref = $params{T}; $T_ref->{msg} = "Hello World"; return; }

        In "Foo Bar":

        use My::Wrapper qw( wrap ); wrap( \&foo_bar ); sub foo_bar { my %params = %{shift()}; my $T_ref = $params{T}; $T_ref->{msg} = "Foo Bar"; return; }

        Then the main module.

        package My::Wrapper; use strict; use warnings; use Exporter 'import'; @EXPORT_OK = qw( wrap ); use DBI; use CGI; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); use HTML::Template; use HTML::Entities; use lib 'code'; use config; ## Security $CGI::DISABLE_UPLOADS = 1; # no uploads! $CGI::POST_MAX = 512*1024; # max 512k post sub wrap { my ( $code_ref ) = @_; my $template = templates::loadTemplate('template'); my %T; my $innerTemplate; my $q = new CGI; my $c; $code_ref->({ q => $q, T => \%T, # etc. }); ## Filling in the template here if($innerTemplate) { # load the template in, put it into %T. my $template = templates::loadTemplate('$innerTemplate'); $template->param($T{innerContent}) if $T{innerContent}; $T{content} = $template->output(); } print $q->header(); $template->param(%T); print $template->output(); }

        I don't know anything about your template, and I'm not sure what I can deduce from what you've posted. If you want each script to have its own template, then you have to let the wrapped function give that back to the wrapper somehow. You could do this by having a special element in %T or have the wrapped code pass out a hash ref with whatever it wants to supply.

        Also, it's important to note that the above code is not tested or anything. When I do this sort of thing myself, I use objects. In that case, I don't go passing things around; the object just sets its own attributes for communication.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://629020]
Approved by FunkyMonk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (7)
As of 2014-09-20 08:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (157 votes), past polls