Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Accessing Template Toolkit Variables

by saintmike (Vicar)
on Sep 29, 2007 at 21:18 UTC ( #641731=perlquestion: print w/replies, xml ) Need Help??

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

Given a Template Toolkit template, I'd like to get access to all the variables it defines. But not from within the template, rather, I'd like another Perl script to extract variables of the template.

My assumption was that variables get stored in a Template::Stash object, but running the code below doesn't return the expected value 'bar'.

Any ideas on what I'm missing?

my $data_string = q{ [% foo = "bar" %] }; use Template; use Template::Stash; my $stash = Template::Stash->new(); my $tmpl = Template->new(STASH => $stash); my $out; $tmpl->process(\$data_string, {}, \$out) or die $tmpl->error(); print $stash->get('foo'), "\n";

Replies are listed 'Best First'.
Re: Accessing Template Toolkit Variables
by Util (Priest) on Sep 30, 2007 at 17:05 UTC

    The documentation says "The Template::Stash module is used to fetch and store template variables.", so I (a recent TT convert) thought your code should work. I did some experimenting:

    As the Anonymous Monk said, the stash is reverting to its prior state after process(). So, unless you use the stash to communicate *all* variable state, your approach does not look workable.

    I also tried the method listed in the "Show All Variables" thread on the TT mailing list, but I could not make it work at all; perhaps the TT code no longer recognizes a bare 'keys' statement as referring to the whole stash.

    Since Template::Stash does handle all the variable get&set, you might be able to cache the last get|set for each variable as Template::Stash handles it via subclassing:

    While this looks *very* promising, it might be limited to only simple variable access. I did not have time to test it on complex (dotted) variable access, where this technique might break down.

    If you figure out a better solution, or get one from another venue, please post it here for future Monks!

      Extended the module to at least nominally handle dotted variables:

      use strict; use warnings; package Template::Capturing::Stash; { use base 'Template::Stash'; our %remembering_hash; sub get { die if @_ != 2; my ( $self, $var_name ) = @_; my $var_value = $self->SUPER::get($var_name); if ( ref $var_name eq 'ARRAY' ) { $var_name = compound_var( @{$var_name} ); } #print "! Get of $var_name = $var_value\n"; $remembering_hash{$var_name} = $var_value; return $var_value; } sub set { die if @_ < 3 or @_ > 4; my ( $self, $var_name, $var_value, $default ) = @_; die "Not yet coded to handle default" if defined $default; my $return_value = $self->SUPER::set( $var_name, $var_value ); if ( ref $var_name eq 'ARRAY' ) { $var_name = compound_var( @{$var_name} ); } #print "! Set of $var_name = $var_value\n"; $remembering_hash{$var_name} = $var_value; return $return_value; } sub compound_var { my @var_name = @_; my @compound_var; foreach my $element ( @var_name ) { unless ( $element eq '0' ) { if ( ref $element eq 'ARRAY' ) { $element = compound_var( @{$element} ); } push @compound_var, $element; } } return join '.', @compound_var; } } 1;
Re: Accessing Template Toolkit Variables
by Anonymous Monk on Sep 30, 2007 at 04:24 UTC
    They get stored, and then they get purged
Re: Accessing Template Toolkit Variables
by Rhandom (Curate) on Oct 01, 2007 at 16:08 UTC
    This topic was recently discussed on the TT mailing list. There were some options given, but they all required passing in a reference to a hash or a sub that were then populated.

    An option that would work in your situation, would be to use Template::Alloy and the poorly documented process_simple method, which has more restrictions than the process method - but doesn't create a copy of the passed in variable stash.

    Template::Alloy also gives you access to features that will be in TT3 such as regex construction and self modifying operators such as //=.

    use Template::Alloy; use Data::Dumper qw(Dumper); my %vars; my $out = ""; my $t = Template::Alloy->new; my $data_str = q{ [% foo = "bar" %] [% bingo.bango.bongo = /matchme/ %] [% a //= []; a.0.b.3 = "C" %] }; $t->process_simple(\$data_str, \%vars, \$out) || die $t->error; print Dumper \%vars; __END__ prints: $VAR1 = { 'a' => [ { 'b' => { '3' => 'C' } } ], 'bingo' => { 'bango' => { 'bongo' => qr/(?-xism:matchme)/ } }, 'foo' => 'bar' };

    Disclaimer - I wrote Template::Alloy so I *may* be a bit biased towards its use.

    my @a=qw(random brilliant braindead); print $a[rand(@a)];

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://641731]
Approved by FunkyMonk
Front-paged by kyle
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (3)
As of 2019-07-24 02:16 GMT
Find Nodes?
    Voting Booth?
    If you were the first to set foot on the Moon, what would be your epigram?

    Results (32 votes). Check out past polls.