NAME
PAB3 - Perl Application Builder
SYNOPSIS
use PAB3;
DESCRIPTION
PAB3
provides a framework for building rapid applications in Perl5. It also includes a template handler for producing output. This part is defined here.
Examples
Following example loads a template from template1.tpx, does a loop over the %ENV variable and produces output on STDOUT.
-------------------------------------------------------------------
test1.pl
-------------------------------------------------------------------
#!/usr/bin/perl -w
use PAB3;
my $pab = PAB3->new();
$pab->make_script_and_run( 'template1.tpx' );
-------------------------------------------------------------------
template1.tpx
-------------------------------------------------------------------
i am from <*=$0*>
my environment looks like:
<* LOOP HASH %ENV *>
<* PRINT $_ . ' = ' . $ENV{$_} . "\n" *>
<* END LOOP *>
METHODS
- new ( [%arg] )
-
Creates a new instance of PAB3 template handler class.
Posible arguments are:
path_cache => path to save parsed templates path_template => path to the template files auto_cache => create cache files automatically. 'path_cache' is required prg_start => begin of program sequence, default is '<*' prg_end => end of program sequence, default is '*>' cmd_sep => command separator, to define more directives in one program sequence, default is ';;' record_name => name of default record in loops, default is '$_' logger => reference to a PAB3::Logger class warn => warn on error, default is OFF die => die on error, default is ON class_name => name of the variable for this class. eg '$pab' It is needed when templates including templates. If its undefined, a variable $PAB3::_CURRENT will be used as a reference to the current PAB3 class.
Example:
$pab = PAB3->new( 'path_cache' => '/path/to/cache', 'path_template' => '/path/to/template-files', );
- setenv ()
-
Set some useful variables to the interpreters environment
these variables are:
$ENV{'SCRIPT_PATH'} : path to the main script $ENV{'SCRIPT'} : name of the main script
- make_script ( $template )
- make_script ( $template, $cache )
- make_script ( $template, '', $package )
- make_script ( $template, $cache, $package )
-
Generates a perl script from $template file. If $cache file is defined the script will be saved into the cache file. If cache file already exists and the template has not been modified, the function will break here an return. If cache file has not been specified the script will be compiled into the memory as a package. The name of this package can be defined in the third parameter. If $package has not been specified the package from
caller(0)
is used.Returns TRUE on success or FALSE on error.
Example:
$pab->make_script( 'template.htm' ) or die $pab->error();
See also run_script, make_script_and_run
- run_script ( $template )
- run_script ( '', $cache )
- run_script ( '', $cache, $package )
-
Runs a perl script which has been generated by make_script(). If $cache file is specified, the script will be loaded from there and be compiled into memory as a package. The name of this package can be defined in the third parameter. If $package has not been specified the package from
caller(0)
is used.Returns a TRUE on success or FALSE on error.
Example:
$pab->run_script( 'template.htm' ) or die $pab->error();
See also make_script, make_script_and_run, PAB3::require_and_run
- make_script_and_run ( $template )
- make_script_and_run ( $template, $cache )
- make_script_and_run ( $template, $cache, $package )
-
Combines the two functions above. If $package has not been specified the package from
caller(0)
is used.Returns a TRUE value on success or FALSE if an error occurs.
Example:
$pab->make_script_and_run( 'template.htm', 'template.pl' ) or die $pab->error();
See also make_script, run_script
- register_loop ( $id, $source, $s_type )
- register_loop ( $id, $source, $s_type, $record, $r_type )
- register_loop ( $id, $source, $s_type, $record, $r_type, $object )
- register_loop ( $id, $source, $s_type, $record, $r_type, $object, $arg )
- register_loop ( $id, $source, $s_type, $record, $r_type, $object, $arg, $fixed )
-
Registers a loop which can be used inside templates.
You do not need to define loops in this way. You can also write it directly in the template. But if you want using hashmaps, you need to go in this way.
Arguments
$id
Loop identifier
$source
the source for the loop.
$s_type
the type of the source. One of these constants: PAB_ARRAY, PAB_HASH or PAB_FUNC
$record
the record for the loop.
$r_type
the type of the record. One of these constants: PAB_SCALAR or PAB_FUNC
$object
a object for $source or $record functions.
$arg
arguments passed to the source if it is a function, as an array reference
$fixed
installes the loop as fixed. it can not be overwritten
Combinations
Following combinations are possible:
-------------------------------------- | Source | Record | Object | -------------------------------------- | PAB_ARRAY | PAB_SCALAR | - | | PAB_ARRAY | PAB_FUNC | yes | | PAB_HASH | PAB_SCALAR | - | | PAB_HASH | PAB_FUNC | yes | | PAB_FUNC | PAB_SCALAR | yes | | PAB_FUNC | PAB_ARRAY | yes | | PAB_FUNC | PAB_HASH | yes | --------------------------------------
Source as Array, Record as Scalar
# definition register_loop( 'id', 'source' => PAB_ARRAY, 'record' => PAB_SCALAR ) # result foreach $record( @source ) { }
Source as Array, Record as Function
# definition register_loop( 'id', 'source' => PAB_ARRAY, 'record' => PAB_FUNC ) # result foreach <iv>( @source ) { &record( <iv> ); }
Source as Array, Record as Function, Object
# definition register_loop( 'id', 'source' => PAB_ARRAY, 'record' => PAB_FUNC, 'object' ) # result foreach <iv>( @source ) { $object->record( <iv> ); }
Source as Hash, Record as Scalar
# definition register_loop( 'id', 'source' => PAB_HASH, 'record' => PAB_SCALAR ) # result foreach $record( keys %source ) { }
Source as Hash, Record as Function
# definition register_loop( 'id', 'source' => PAB_HASH, 'record' => PAB_FUNC ) # result foreach <iv>( keys %source ) { &record( <iv> ); }
Source as Hash, Record as Function, Object
# definition register_loop( 'id', 'source' => PAB_HASH, 'record' => PAB_FUNC, 'object' ) # result foreach <iv>( keys %source ) { $object->record( <iv> ); }
Source as Function, Record as Scalar
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_SCALAR ) # result while( $record = &source( @$arg ) ) { }
Source as Function, Record as Scalar, Object
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_SCALAR, 'object' ) # result while( $record = $object->source( @$arg ) ) { }
Source as Function, Record as Array
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_ARRAY ) # result while( @record = &source( @$arg ) ) { }
Source as Function, Record as Hash
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_HASH ) # result while( %record = &source( @$arg ) ) { }
Source as Function, Record as Function
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_FUNC ) # result while( <iv> = &source( @$arg ) ) { &record( <iv> ); }
Source as Function, Record as Function, Object
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_FUNC, 'object' ) # result while( <iv> = $object->source( @$arg ) ) { &record( $object, <iv> ); }
Examples
Example of a loop over an array with record as subroutine:
use PAB3 qw(:const); my @Array1 = ( 1, 2, 3 ); $pab->register_loop( 'MYLOOP', 'Array1' => PAB_ARRAY , 'init_record' => PAB_FUNC ); sub init_record { $Record = shift; ... }
Example of an enumeration loop:
$pab->register_loop( 'MYLOOP', 'enum' => PAB_FUNC, 'Record' => PAB_SCALAR ); $Counter = 10; sub enum { if( $Counter == 0 ) { $Counter = 10; return 0; } return $Counter --; }
--- inside the template ---
<* LOOP MYLOOP *> <* PRINT $Record . "\n" *> <* END LOOP *>
See also
- add_hashmap ( $loop_id, $hashname, $fieldmap )
- add_hashmap ( $loop_id, $hashname, $fieldmap, $hm_save )
-
Add a hashmap to the parser. Hashmaps are designed to translate hashes in templates into arrays in the parsed script. For example: you use $var->{'Key'} in your template. With a hashmap you can convert it into an array like $var->[0] without taking care of the indices. This can noticable make the execution time faster.
Parameters
$loop_id
Defines the loop to search for If it is defined the program sequences inside the loop will be converted. Otherwise the complete template will be used for.
$hashname
Specifies the name of the hash to be translated.
$fieldmap
Can be a reference to an array of fieldnames or a reference to a hash containing fieldnames as keys and the assiocated indices as values.
$hm_save
If $fieldmap is an arrayref, the new generated hashmap can be saved in this parameter.
Return Values
Returns TRUE on success or FALSE if it fails.
Example
@data = ( [ 'Smith', 'John', 33 ], [ 'Thomson', 'Peggy', 45 ], [ 'Johanson', 'Gustav', 27 ], ); @fields = ( 'Name', 'Prename', 'Age' ); $pab->register_loop( 'Person', 'data', PAB_ARRAY, 'per', PAB_SCALAR ) $pab->add_hashmap( 'Person', 'per', \@fields ); $pab->make_script_and_run( 'template' );
--- template ---
<* LOOP Person *> <* = $per->{'Prename'} . ' ' . $per->{'Name'} *> is <* = $per->{'Age'} *> years old <* END LOOP *>
Warning
If an empty result from a db query is returned, no hashmap can be created. If your template needs to be compiled and uses hashmaps, which are empty, you will get an error. You should recompile affected templates once by running them with valid hashmaps. Or you can use a hashmap cache handler. See more at PAB3::HashMapCache.
- reset ()
-
Resets loops and hashmaps in the PAB class.
Returns allways a TRUE value.
- require ( $filename )
-
Loads the required file and compiles it into a package and runs it once it has been changed.
Example:
&PAB3::require( 'config.inc.pl' );
- require_and_run ( $filename )
-
Loads the required file and compiles it into a package once it has been changed. Runs it on every call.
Example:
&PAB3::require_and_run( 'dosomething.pl' );
PAB LANGUAGE SYNTAX
The little extended language is needed to extract the PAB and Perl elements from the rest of the template. By default program sequences are includes in <* ... *> and directives are separated by ;; . This parameters can be overwritten in new().
Some Examples
<p><* PRINT localtime *></p>
<*
my $MyVar = int( rand( 3 ) );;
my @MyText =
(
'I wish you a nice day.',
'Was happy to see you.',
'Would be nice to see you back.'
)
*>
<* IF $MyVar == 0 *>
<p>I wish you a nice day.</p>
<* ELSIF $MyVar == 1 *>
<p>Was happy to see you.</p>
<* ELSE *>
<p>Would be nice to see you back.</p>
<* END IF *>
<!-- OR SHORTLY -->
<p><* PRINT $MyText[$MyVar] *></p>
Directives
The following list explains the directives available in PAB3. The description is using the default program and command separators. All directives are case insensitive.
- PRINT <expression>
- = <expression>
-
Prints the output returned from <expression>. Performance notice: Tests showed the double of speed when expressions are combined as strings instead of multiple argmuents. For example:
faster: <* PRINT $x . ' some data: ' . $str *> slower: <* PRINT $x, ' some data: ', $str *>
Joining several PRINT directives into on directive does not realy affect to the speed, because the optimizer will do it automatically.
<* PRINT <expression> *>
or shortly
<* =<expression> *>
Example:
<* PRINT $0, "\n" *> <* PRINT 'Now: ' . time . "\n" *> <* = 'Or formated: ' . &PAB3::Utils::strftime( '%c', time ) *>
- : <expression>
- <expression>
-
Executes <expression> wihout printing the output. This is also the default action if no directive has been specified.
<* : <expression> *>
or
<* <expression> *>
Example:
<* : $MyVar = 1 *> <* : &mySub( $MyVar ) *> <* $X = $Y *>
- IF <condition>
- ELSIF <condition>
- ELSE
- END IF
-
Enclosed block is processed if the <condition> is true.
<* IF <condition> *> ... <* ELSIF <condition> *> ... <* ELSE *> ... <* END IF *>
- INCLUDE <template>
-
Process another template file. Please note the "class_name" in new().
<* INCLUDE <template.file> *>
- -LOOP-
- LOOP <id>
- LOOP <id> <exp1>
- LOOP <id> <exp1> <exp2>
- END LOOP
-
Performs a predefined loop or a loop which has been registered by register_loop. In predifened loops like ARRAY, FOR and HASH, <exp1> is use as source and <exp2> is used as record. In userdefined loops <exp1> is used as record and <exp2> is used as argument.
<* LOOP <id> [<exp1> [<exp2>]] *> ... <* END LOOP *>
Theses loops are predefined:
<* LOOP ARRAY <array> [<record>] *> <* LOOP FOR <array> [<record>] *> <* LOOP HASH <hash> [<record>] *>
Example of an ARRAY loop: (FOR does the same like ARRAY)
<* LOOP ARRAY @INC $_ *> <* PRINT $_ . "\n" *> <* END LOOP *>
Example of a HASH loop:
<* LOOP HASH %ENV $_ *> <* PRINT $_ . ' = ' . $ENV{$_} . "\n" *> <* END LOOP *>
An example of a self defined loop:
This example also shows the use of the PAB3::DB class.
--- inside the perl script ---
use PAB3 qw(:const); use PAB3::DB; use PAB3::Utils qw(:default); $pab = PAB3->new( ... ); $db = PAB3::DB->connect( ... ); $r_gb = $db->query( 'SELECT * FROM guestbook ORDER BY Time DESC' ); $pab->register_loop( 'GUESTBOOK', 'fetch_hash', PAB_FUNC, 'row', PAB_HASH, '$r_gb' ); $pab->make_script_and_run( 'template.htm' );
--- inside the template ---
<* LOOP GUESTBOOK *> <* PRINT $row{'Submitter'} *> wrote at <* PRINT &strftime( '%c', $row{'Time'} ) *> the following comment:<br> <blockquote><* PRINT $row{'Comment'} *></blockquote> <hr noshade size="1"> <* END LOOP *>
Second example of a self defined loop:
This example shows a implementation of guestbook example above, which can run faster. It uses an array instead of a hash as record. The Translation will be set by add_hashmap(). The template must not be changed.
--- inside the perl script ---
use PAB3 qw(:const); use PAB3::DB; use PAB3::Utils qw(:default); $pab = PAB3->new( ... ); $db = PAB3::DB->connect( ... ); $r_gb = $db->query( 'SELECT * FROM guestbook ORDER BY Time DESC' ); $pab->register_loop( 'GUESTBOOK', 'fetch_array', PAB_FUNC, 'row', PAB_ARRAY, '$r_gb' ); $pab->add_hashmap( 'GUESTBOOK', 'row', [ $r_gb->fetch_names() ] ); $pab->make_script_and_run( 'template.htm' );
--- inside the template ---
<* LOOP GUESTBOOK *> <* PRINT $row{'Submitter'} *> wrote at <* PRINT &strftime( '%c', $row{'Time'} ) *> the following comment:<br> <blockquote><* PRINT $row{'Comment'} *></blockquote> <hr noshade size="1"> <* END LOOP *>
See also register_loop, add_hashmap, PAB3::DB, PAB3::Utils
- SUB <expression>
- END SUB
-
Defines a subroutine in the style
local <expression> = sub { ... };
.<* SUB <expression> *> ... <* END SUB *>
Example:
<* SUB *action *> <* PRINT $ENV{'SCRIPT'} . '?do=' . ( $_[0] || '' ) *> <* END SUB *> <a href="<* &action( 'open' ) *>">Open</a>
- COMMENTS
-
Comments are copied.
<* #... *>
Example:
# comment out directives. <* #PRINT $foo *>
- !X <directive>
-
This special directive prints the content in <directive> as a new directive. It can be useful to generate templates from templates.
<* !X <directive> *>
Example:
<* $foo = '$bar' *> <* !X PRINT $foo *> produces: <* PRINT $bar *> <* !X PRINT "\$foo" *> produces: <* PRINT $foo *>
EXPORTS
By default nothing is exported. To export constants like PAB_SCALAR etc. you can use the export tag ":const"
AUTHORS
Christian Mueller <christian_at_hbr1.com>
COPYRIGHT
The PAB3 module is free software. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.