3 CGI::Ex::App - Anti-framework application framework.
9 -------- File: /cgi-bin/my_cgi --------
14 use base qw(CGI::Ex::App);
16 __PACKAGE__->navigate;
20 return \ "Hello World!";
23 Well, you should put your content in an external file...
25 -------- File: /cgi-bin/my_cgi --------
30 use base qw(CGI::Ex::App);
32 __PACKAGE__->navigate;
34 sub base_dir_abs { '/var/www/templates' }
37 -------- File: /var/www/templates/my_cgi/main.html --------
41 How about if we want to add substitutions...
43 -------- File: /cgi-bin/my_cgi --------
48 use base qw(CGI::Ex::App);
50 __PACKAGE__->navigate;
52 sub base_dir_abs { '/var/www/templates' }
58 date => sub { scalar localtime },
63 -------- File: /var/www/templates/my_cgi/main.html --------
65 [% greeting %] World! ([% date %])
68 How about a form with validation (inluding javascript validation)...
70 -------- File: /cgi-bin/my_cgi --------
75 use base qw(CGI::Ex::App);
77 __PACKAGE__->navigate;
79 sub base_dir_abs { '/var/www/templates' }
81 sub main_hash_swap { {date => sub { scalar localtime }} }
89 sub main_hash_validation {
94 compare1_error => 'Please enter a value less than 101',
96 compare2_error => 'Please enter a value greater than 0',
103 my $form = $self->form;
105 $self->add_to_form({was_correct => ($form->{'guess'} == 23)});
107 return 0; # indicate to show the page without trying to move along
111 -------- File: /var/www/templates/my_cgi/main.html --------
113 <h2>Hello World! ([% date %])</h2>
116 <b>Correct!</b> - The number was [% guess %].<br>
118 <b>Incorrect</b> - The number was not [% guess %].<br>
121 <form name="[% form_name %]" method="post">
123 Enter a number between 1 and 100: <input type="text" name="guess"><br>
124 <span id="guess_error" style="color:red">[% guess_error %]</span><br>
126 <input type="submit">
132 There are infinite possibilities. There is a longer "SYNOPSIS" after
133 the process flow discussion and more examples near the end of this
134 document. It is interesting to note that there have been no databases
135 so far. CGI::Ex::App is Controller/Viewer that is somewhat Model
140 Fill in the blanks and get a ready made web application.
142 This module is somewhat similar in spirit to CGI::Application,
143 CGI::Path, and CGI::Builder and any other "CGI framework." As with
144 the others, CGI::Ex::App tries to do as much of the mundane things, in
145 a simple manner, without getting in the developer's way. However,
146 there are various design patterns for CGI applications that
147 CGI::Ex::App handles for you that the other frameworks require you to
148 bring in extra support. The entire CGI::Ex suite has been taylored to
149 work seamlessly together. Your mileage in building applications may
152 If you build applications that submit user information, validate it,
153 re-display it, fill in forms, or separate logic into separate modules,
154 then this module may be for you. If all you need is a dispatch
155 engine, then this still may be for you. If all you want is to look at
156 user passed information, then this may still be for you. If you like
157 writing bare metal code, this could still be for you. If you don't want
158 to write any code, this module will help - but you still need to
159 provide your key actions and html.
161 One of the great benefits of CGI::Ex::App vs. Catalyst or Rails style
162 frameworks is that the model of CGI::Ex::App can be much more abstract.
163 And models often are abstract.
165 =head1 DEFAULT PROCESS FLOW
167 The following pseudo-code describes the process flow
168 of the CGI::Ex::App framework. Several portions of the flow
169 are encapsulated in hooks which may be completely overridden to give
170 different flow. All of the default actions are shown. It may look
171 like a lot to follow, but if the process is broken down into the
172 discrete operations of step iteration, data validation, and template
173 printing the flow feels more natural.
177 The process starts off by calling ->navigate.
185 # dying errors will run the ->handle_error method
192 The nav_loop method will run as follows:
195 ->path (get the array of path steps)
196 # ->path_info_map_base (method - map ENV PATH_INFO to form)
197 # look in ->form for ->step_key
198 # make sure step is in ->valid_steps (if defined)
201 # navigation stops if true
203 foreach step of path {
206 # check ->allow_morph
207 # check ->allow_nested_morph
208 # ->morph_package (hook - get the package to bless into)
209 # ->fixup_after_morph if morph_package exists
210 # if no package is found, process continues in current file
212 ->path_info_map (hook - map PATH_INFO to form)
217 # only called if run_step returned false (page not printed)
218 ->next_step (hook) # find next step and add to path
219 ->set_ready_validate(0) (hook)
222 # only called if morph worked
223 # ->fixup_before_unmorph if blessed to current package
225 # exit loop if ->run_step returned true (page printed)
227 } end of foreach step
230 # navigation stops if true
233 ->insert_path (puts the default step into the path)
234 ->nav_loop (called again recursively)
238 =head2 run_step (hook)
240 For each step of the path the following methods will be run
241 during the run_step hook.
245 # exits nav_loop if true
248 # skips this step if true (stays in nav_loop)
250 ->prepare (hook - defaults to true)
252 ->info_complete (hook - ran if prepare was true)
253 ->ready_validate (hook)
254 return false if ! ready_validate
255 ->validate (hook - uses CGI::Ex::Validate to validate form info)
256 ->hash_validation (hook)
263 returns true if validate is true or if nothing to validate
265 ->finalize (hook - defaults to true - ran if prepare and info_complete were true)
267 if ! ->prepare || ! ->info_complete || ! ->finalize {
275 # merge form, base, common, and fill into merged fill
276 # merge form, base, common, swap, and errors into merged swap
277 ->print (hook - passed current step, merged swap hash, and merged fill)
278 ->file_print (hook - uses base_dir_rel, name_module, name_step, ext_print)
279 ->swap_template (hook - processes the file with CGI::Ex::Template)
280 ->template_args (hook - passed to CGI::Ex::Template->new)
281 ->fill_template (hook - fills the any forms with CGI::Ex::Fill)
282 ->fill_args (hook - passed to CGI::Ex::Fill::fill)
283 ->print_out (hook - print headers and the content to STDOUT)
285 ->post_print (hook - used for anything after the print process)
287 # return true to exit from nav_loop
291 # exits nav_loop if true
295 It is important to learn the function and placement of each of the
296 hooks in the process flow in order to make the most of CGI::Ex::App.
297 It is enough to begin by learning a few common hooks - such as
298 hash_validation, hash_swap, and finalize, and then learn about other
299 hooks as needs arise. Sometimes, it is enough to simply override the
300 run_step hook and take care of processing the entire step yourself.
302 Because of the hook based system, and because CGI::Ex::App uses
303 sensible defaults, it is very easy to override a little or a lot which
304 ends up giving the developer a lot of flexibility.
306 Additionally, it should be possible to use CGI::Ex::App with the other
307 frameworks such as CGI::Application or CGI::Prototype. For these you
308 could simple let each "runmode" call the run_step hook of CGI::Ex::App
309 and you will instantly get all of the common process flow for free.
311 =head1 MAPPING URI TO STEP
313 The default out of the box configuration will map URIs to steps as follows:
315 # Assuming /cgi-bin/my_app is the program being run
320 WHY: No other information is passed. The path method is
321 called which eventually calls ->default_step which
324 URI: /cgi-bin/my_app?foo=bar
327 WHY: Same as previous example except that QUERY_STRING
328 information was passed and placed in form.
330 URI: /cgi-bin/my_app?step=my_step
332 FORM: {step => "my_step"}
333 WHY: The path method is called which looks in $self->form
334 for the key ->step_key (which defaults to "step").
336 URI: /cgi-bin/my_app?step=my_step&foo=bar
338 FORM: {foo => "bar", step => "my_step"}
339 WHY: Same as before but has other parameters were passed.
341 URI: /cgi-bin/my_app/my_step
343 FORM: {step => "my_step"}
344 WHY: The path method is called which called path_info_map_base
345 which matched $ENV{'PATH_INFO'} using the default regex
346 of qr{^/(\w+)$} and place the result in
347 $self->form->{$self->step_key}. Path then looks in
348 $self->form->{$self->step_key} for the initial step. See
349 the path_info_map_base method for more information.
351 URI: /cgi-bin/my_app/my_step?foo=bar
353 FORM: {foo => "bar", step => "my_step"}
354 WHY: Same as before but other parameters were passed.
356 URI: /cgi-bin/my_app/my_step?step=other_step
358 FORM: {step => "other_step"}
359 WHY: The same procedure took place, but when the PATH_INFO
360 string was matched, the form key "step" already existed
361 and was not replaced by the value from PATH_INFO.
363 The remaining examples in this section are based on the assumption
364 that the following method is installed in your script.
366 sub my_step_path_info_map {
368 [qr{^/\w+/(\w+)/(\d+)$}, 'foo', 'id'],
369 [qr{^/\w+/(\w+)$}, 'foo'],
370 [qr{^/\w+/(.+)$}, 'anything_else'],
374 URI: /cgi-bin/my_app/my_step/bar
377 WHY: The step was matched as in previous examples using
378 path_info_map_base. However, the form key "foo"
379 was set to "bar" because the second regex returned
380 by the path_info_map hook matched the PATH_INFO string
381 and the corresponding matched value was placed into
382 the form using the keys specified following the regex.
384 URI: /cgi-bin/my_app/my_step/bar/1234
386 FORM: {foo => "bar", id => "1234"}
387 WHY: Same as the previous example, except that the first
388 regex matched the string. The first regex had two
389 match groups and two form keys specified. Note that
390 it is important to order your match regexes in the
391 order that will match the most data. The third regex
392 would also match this PATH_INFO.
394 URI: /cgi-bin/my_app/my_step/some/other/type/of/data
396 FORM: {anything_else => 'some/other/type/of/data'}
397 WHY: Same as the previous example, except that the third
400 URI: /cgi-bin/my_app/my_step/bar?bling=blang
402 FORM: {foo => "bar", bling => "blang"}
403 WHY: Same as the first step, but additional QUERY_STRING
404 information was passed.
406 URI: /cgi-bin/my_app/my_step/one%20two?bar=three%20four
408 FORM: {anything_else => "one two", bar => "three four"}
409 WHY: The third path_info_map regex matched. Note that the
410 %20 in bar was unescaped by CGI::param, but the %20
411 in anything_else was unescaped by Apache. If you are
412 not using Apache, this behavior may vary. CGI::Ex::App
413 doesn't decode parameters mapped from PATH_INFO.
415 See the path method for more information about finding the initial step
418 The form method calls CGI::Ex::form which uses CGI::param to retrieve
419 GET and POST parameters. See the form method for more information on
420 how GET and POST parameters are parsed.
422 See the path_info_map_base method, and path_info_map hook for more information
423 on how the path_info maps function.
425 Using the following code is very useful for determing what hooks have
428 use CGI::Ex::Dump qw(debug);
432 debug $self->dump_history, $self->form;
435 =head1 ADDING DATA VALIDATION TO A STEP
437 CGI::Ex::App uses CGI::Ex::Validate for its data validation. See CGI::Ex::Validate
438 for more information about the many ways you can validate your data.
440 The default hash_validation hook returns an empty hashref. This means that passed
441 in data is all valid and the script will automatically call the step's finalize method.
443 The following shows how to some contrived validation to a step called "my_step".
445 sub my_step_hash_validation {
449 match => 'm/^(\w+)$/',
450 match_error => 'The $field field may only contain word characters',
458 validate_if => 'password',
459 equals => 'password',
463 enum => [qw(animal vegetable mineral)],
468 The step will continue to display the html form until all of the fields pass
471 See the hash_validation hook and validate hook for more information about how
474 =head1 ADDING JAVASCRIPT DATA VALIDATION TO A STEP
476 You must first provide a hash_validation hook as explained in the previous section.
478 Once you have a hash_validation hook, you would place the following tags
479 into your HTML template.
481 <form name="[% form_name %]" method="post">
486 The "form_name" swap-in places a name on the form that the javascript returned by
487 the js_validation swap-in will be able to find and check for validity.
489 See the hash_validation, js_validation, and form_name hooks for more information.
491 Also, CGI::Ex::validate.js allows for inline errors in addition to or in replacement
492 of an alert message. To use inline errors, you must provide an element in your
493 HTML document where this inline message can be placed. The common way to do it is as
496 <input type="text" name="username"><br>
497 <span class="error" id="username_error">[% username_error %]</span>
499 The span around the error allows for the error css class and it provides a location
500 that the Javascript validation can populate with errors. The [% username_error %] provides
501 a location for errors generated on the server side to be swapped in. If there was no error
502 the [% username_error %] tag would default to "".
504 =head1 ADDING ADDITIONAL TEMPLATE VARIABLES
506 All variables returned by the hash_base, hash_common, hash_form, hash_swap, and
507 hash_errors hooks are available for swapping in templates.
509 The following shows how to add variables using the hash_swap hook on the step "main".
514 choices => [qw(one two three)],
515 "warn" => sub { warn @_ },
519 You could also return the fields from the hash_common hook and they would be available
520 in both the template swapping as well as form filling.
522 See the hash_base, hash_common, hash_form, hash_swap, hash_errors, swap_template, and
523 template_args hooks for more information.
525 The default template engine used is CGI::Ex::Template which is Template::Toolkit compatible.
526 See the CGI::Ex::Template or Template::Toolkit documentation for the types of data
527 that can be passed, and for the syntax that can be used.
529 =head1 ADDING ADDITIONAL FORM FILL VARIABLES
531 All variables returned by the hash_base, hash_common, hash_form, and hash_fill hooks
532 are available for filling html fields in on templates.
534 The following shows how to add variables using the hash_fill hook on the step "main".
539 choices => [qw(one two three)],
543 You could also return the fields from the hash_common hook and they would be available
544 in both the form filling as well as in the template swapping.
546 See the hash_base, hash_common, hash_form, hash_swap, hash_errors, fill_template, and
547 fill_args hooks for more information.
549 The default form filler is CGI::Ex::Fill which is similar to HTML::FillInForm but
550 has several benefits. See the CGI::Ex::Fill module for the available options.
552 =head1 FINDING TEMPLATES AND VALIDATION FILES
554 CGI::Ex::App tries to help your applications use a good template directory layout, but allows
555 for you to override everything.
557 External template files are used for storing your html templates and
558 for storing your validation files (if you use externally stored
561 The default file_print hook will look for content on your file system,
562 but it can also be completely overridden to return a reference to a
563 scalar containing the contents of your file. Actually it can return
564 anything that CGI::Ex::Template (Template::Toolkit compatible) will
565 treat as input. This templated html is displayed to the user during
566 any step that enters the "print" phase.
568 Similarly the default file_val hook will look for a validation file on
569 the file system, but it too can return a reference to a scalar
570 containing the contents of a validation file. It may actually return
571 anything that the CGI::Ex::Validate get_validation method is able to
572 understand. This validation is used by the default "info_complete"
573 method for verifying if the submitted information passes its specific
574 checks. A more common way of inlining validation is to return a
575 validation hash from a hash_validation hook override.
577 If the default file_print and file_val hooks are used, the following methods
578 are employed for finding templates and validation files on your filesystem (they
579 are also documented more in the HOOKS AND METHODS section.
585 Absolute path or arrayref of paths to the base templates directory. Default "".
589 Relative path inside of the base_dir_abs directory where content can be found. Default "".
593 Directory inside of base_dir_rel where files for the current CGI (module) will be
594 stored. Default value is $ENV{SCRIPT_NAME} with path and extension removed.
598 Used with ext_print and ext_val for creating the filename that will be looked for
599 inside of the name_module directory. Default value is the current step.
601 =item ext_print and ext_val
603 Filename extensions added to name_step to create the filename looked for
604 inside of the name_module directory. Default is "html" for ext_print and "val"
609 It may be easier to understand the usage of each of these methods by showing
610 a contrived example. The following is a hypothetical layout for your templates:
612 /home/user/templates/
613 /home/user/templates/chunks/
614 /home/user/templates/wrappers/
615 /home/user/templates/content/
616 /home/user/templates/content/my_app/
617 /home/user/templates/content/my_app/main.html
618 /home/user/templates/content/my_app/step1.html
619 /home/user/templates/content/my_app/step1.val
620 /home/user/templates/content/another_cgi/main.html
622 In this example we would most likely set values as follows:
624 base_dir_abs /home/user/templates
628 The name_module method defaults to the name of the running program, but
629 with the path and extension removed. So if we were running
630 /cgi-bin/my_app.pl, /cgi-bin/my_app, or /anypath/my_app, then
631 name_module would default to "my_app" and we wouldn't have to
632 hard code the value. Often it is wise to set the value anyway so
633 that we can change the name of the cgi script without effecting
634 where template content should be stored.
636 Continuing with the example and assuming that name of the step that
637 the user has requested is "step1" then the following values would be
640 base_dir_abs /home/user/templates
647 file_print content/my_app/step1.html
648 file_val /home/user/templates/content/my_app/step1.val
650 The call to the template engine would look something like
653 my $t = $self->template_obj({
654 INCLUDE_PATH => $self->base_dir_abs,
657 $t->process($self->file_print($step), \%vars);
659 The template engine would then look for the relative file
660 inside of the absolute paths (from base_dir_abs).
662 The call to the validation engine would pass the absolute
663 filename that is returned by file_val.
665 The name_module and name_step methods can return filenames with
666 additional directories included. The previous example could
667 also have been setup using the following values:
669 base_dir_abs /home/user/templates
671 name_module content/my_app
673 In this case the same values would be returned for the file_print and file_val hooks
674 as were returned in the previous setup.
676 =head1 SYNOPSIS (A LONG "SYNOPSIS")
678 This example script would most likely be in the form of a cgi, accessible via
679 the path http://yourhost.com/cgi-bin/my_app (or however you do CGIs on
680 your system. About the best way to get started is to paste the following
681 code into a cgi script (such as cgi-bin/my_app) and try it out. A detailed
682 walk-through follows in the next section. There is also a longer recipe
683 database example at the end of this document that covers other topics including
684 making your module a mod_perl handler.
686 ### File: /var/www/cgi-bin/my_app (depending upon Apache configuration)
687 ### --------------------------------------------
691 use base qw(CGI::Ex::App);
692 use CGI::Ex::Dump qw(debug);
694 __PACKAGE__->navigate;
696 # my $obj = __PACKAGE__->new;
701 ###------------------------------------------###
705 debug shift->dump_history;
708 sub main_hash_validation {
710 'general no_alert' => 1,
711 'general no_confirm' => 1,
712 'group order' => [qw(username password password2)],
718 match_error => 'You may only use letters and numbers.',
725 equals => 'password',
730 sub main_file_print {
731 # reference to string means ref to content
732 # non-reference means filename
733 return \ "<h1>Main Step</h1>
734 <form method=post name=[% form_name %]>
735 <input type=hidden name=step>
738 <td><b>Username:</b></td>
739 <td><input type=text name=username><span style='color:red' id=username_error>[% username_error %]</span></td>
741 <td><b>Password:</b></td>
742 <td><input type=text name=password><span style='color:red' id=password_error>[% password_error %]</span></td>
744 <td><b>Verify Password:</b></td>
745 <td><input type=text name=password2><span style='color:red' id=password2_error>[% password2_error %]</span></td>
747 <tr><td colspan=2 align=right><input type=submit></td></tr>
757 if ($self->form->{'username'} eq 'bar') {
758 $self->add_errors(username => 'A trivial check to say the username cannot be "bar"');
762 debug $self->form, "Do something useful with form here in the finalize hook.";
765 $self->add_to_swap({success_msg => "We did something"});
766 $self->append_path('success');
767 $self->set_ready_validate(0);
771 sub success_file_print {
772 \ "<div style=background:lightblue>
773 <h1>Success Step - [% success_msg %]</h1>
774 Username: <b>[% username %]</b><br>
775 Password: <b>[% password %]</b><br>
782 Note: This example would be considerably shorter if the html file
783 (file_print) and the validation file (file_val) had been placed in
784 separate files. Though CGI::Ex::App will work "out of the box" as
785 shown it is more probable that any platform using it will customize
786 the various hooks to their own tastes (for example, switching print to
787 use a templating system other than CGI::Ex::Template).
789 =head1 SYNOPSIS STEP BY STEP
791 This section goes step by step over the previous example.
793 Well - we start out with the customary CGI introduction.
798 use base qw(CGI::Ex::App);
799 use CGI::Ex::Dump qw(debug);
801 Note: the "use base" is not normally used in the "main" portion of a script.
802 It does allow us to just do __PACKAGE__->navigate.
804 Now we need to invoke the process:
806 __PACKAGE__->navigate;
808 # my $obj = __PACKAGE__->new;
812 Note: the "exit" isn't necessary - but it is kind of nice to infer
813 that process flow doesn't go beyond the ->navigate call.
815 The navigate routine is now going to try and "run" through a series of
816 steps. Navigate will call the ->path method which should return an
817 arrayref containing the valid steps. By default, if path method has
818 not been overridden, the path method will default first to the step
819 found in form key named ->step_name, then it will fall to the contents
820 of $ENV{'PATH_INFO'}. If navigation runs out of steps to run it will
821 run the step found in ->default_step which defaults to 'main'. So the
822 URI '/cgi-bin/my_app' would run the step 'main' first by default. The
823 URI '/cgi-bin/my_app?step=foo' would run the step 'foo' first. The
824 URI '/cgi-bin/my_app/bar' would run the step 'bar' first.
826 CGI::Ex::App allows for running steps in a preset path or each step may
827 choose the next step that should follow. The navigate
828 method will go through one step of the path at a time and see if it is
829 completed (various methods determine the definition of "completed").
830 This preset type of path can also be automated using the CGI::Path
831 module. Rather than using a preset path, CGI::Ex::App also has
832 methods that allow for dynamic changing of the path, so that each step
833 can determine which step to do next (see the jump, append_path,
834 insert_path, and replace_path methods).
836 During development it would be nice to see what happened during the
837 course of our navigation. This is stored in the arrayref contained in
838 ->history. There is a method that is called after all of the navigation
839 has taken place called "post_navigate". This chunk will display history after we
840 have printed the content.
843 debug shift->dump_history;
844 } # show what happened
846 Ok. Finally we are looking at the methods used by each step of the path. The
847 hook mechanism of CGI::Ex::App will look first for a method ${step}_${hook_name}
848 called before falling back to the method named $hook_name. Internally in the
849 code there is a call that looks like $self->run_hook('hash_validation', $step). In
850 this case the step is main. The dispatch mechanism finds our method at the following
853 sub main_hash_validation { ... }
855 The process flow will see if the data is ready to validate. Once it is ready
856 (usually when the user presses the submit button) the data will be validated. The
857 hash_validation hook is intended to describe the data and will be tested
858 using CGI::Ex::Validate. See the CGI::Ex::Validate perldoc for more
859 information about the many types of validation available.
861 sub main_file_print { ... }
863 The navigation process will see if user submitted information (the form)
864 is ready for validation. If not, or if validation fails, the step needs to
865 be printed. Eventually the file_print hook is called. This hook should
866 return either the filename of the template to be printed, or a reference
867 to the actual template content. In this example we return a reference
868 to the content to be printed (this is useful for prototyping applications
869 and is also fine in real world use - but generally production applications
870 use external html templates).
872 A few things to note about the template:
874 First, we add a hidden form field called step. This will be filled in
875 automatically at a later point with the current step we are on.
877 We provide locations to swap in inline errors.
879 <span style="color:red" id="username_error">[% username_error %]</span>
881 As part of the error html we name each span with the name of the error. This
882 will allow for us to have Javascript update the error spots when the javascript
885 At the very end we add the TT variable [% js_validation %]. This swap in is
886 provided by the default hash_base hook and will provide for form data to be
887 validated using javascript.
889 Once the process flow has deemed that the data is validated, it then calls
890 the finalize hook. Finalize is where the bulk of operations should go.
891 We'll look at it more in depth.
895 my $form = $self->form;
897 At this point, all of the validated data is in the $form hashref.
899 if ($form->{'username'} eq 'bar') {
900 $self->add_errors(username => 'A trivial check to say the username cannot be "bar"');
904 It is most likely that though the data is of the correct type and formatting,
905 it still isn't completely correct. This previous section shows a hard coded
906 test to see if the username was 'bar'. If it was then an appropriate error will
907 be set, the routine returns 0 and the run_step process knows that it needs to
908 redisplay the form page for this step. The username_error will be shown inline.
909 The program could do more complex things such as checking to see if the username
910 was already taken in a database.
912 debug $form, "Do something useful with form here in the finalize hook.";
914 This debug $form piece is simply a place holder. It is here that the program would
915 do something useful such as add the information to a database.
918 $self->add_to_swap({success_msg => "We did something"});
920 Now that we have finished finalize, we add a message that will be passed to the template
923 $self->append_path('success');
924 $self->set_ready_validate(0);
926 The program now needs to move on to the next step. In this case we want to
927 follow with a page that informs us we succeeded. So, we append a step named "success".
928 We also call set_ready_validate(0) to inform the navigation control that the
929 form is no longer ready to validate - which will cause the success page to
930 print without trying to validate the data. It is normally a good idea
931 to set this as leaving the engine in a "ready to validate" state can result
932 in an recursive loop (that will be caught).
937 We then return 1 which tells the engine that we completed this step successfully
938 and it needs to move on to the next step.
940 Finally we run the "success" step because we told it to. That step isn't
941 ready to validate so it prints out the template page.
943 For more of a real world example, it would be good to read the sample recipe db
944 application included at the end of this document.
946 =head1 AVAILABLE METHODS / HOOKS
948 CGI::Ex::App's dispatch system works on the principles of hooks (which
949 are essentially glorified method lookups). When the run_hook method
950 is called, CGI::Ex::App will look for a corresponding method call for
951 that hook for the current step name. It is perhaps easier to show than
954 If we are calling the "print" hook for the step "edit" we would call
957 $self->run_hook('print', 'edit', $template, \%swap, \%fill);
959 This would first look for a method named "edit_print". If it is unable to
960 find a method by that name, it will look for a method named "print". If it
961 is unable to find this method - it will die.
963 If allow_morph is set to true, the same methods are searched for but it becomes
964 possible to move some of those methods into an external package.
966 See the discussions under the methods named "find_hook" and "run_hook" for more details.
968 The following is the alphabetical list of methods and hooks.
972 =item allow_morph (method)
974 Should return true if this step is allowed to "morph" the current App
975 object into another package. Default is false. It is passed a single
976 argument of the current step. For more granularity, if true value is
977 a hash, the step being morphed to must be in the hash.
979 To enable morphing for all steps, add the following:
981 sub allow_morph { 1 }
983 To enable morph on specific steps, do either of the following:
995 my ($self, $step) = @_;
996 return $step =~ /^(edit|delete)$/;
999 See the morph "hook" for more information.
1001 =item allow_nested_morph (method)
1003 Similar to the allow_morph hook, but allows for one more level of morphing.
1004 This is useful in cases where the base class was morphed early on, or
1005 if a step needs to call a sub-step but morph first.
1007 See the allow_morph and the morph method for more information.
1009 Should return a boolean value or hash of allowed steps - just as the
1010 allow_morph method does.
1012 =item append_path (method)
1014 Arguments are the steps to append. Can be called any time. Adds more
1015 steps to the end of the current path.
1017 =item auth_args (method)
1019 Should return a hashref that will be passed to the new method of CGI::Ex::Auth.
1020 It is augmented with arguments that integrate it into CGI::Ex::App.
1022 See the get_valid_auth method and the CGI::Ex::Auth documentation.
1026 login_header => '<h1>My login header</h1>',
1027 login_footer => '[% TRY %][% INCLUDE login/login_footer.htm %][% CATCH %]<!-- [% error %] -->[% END %]',
1028 secure_hash_keys => [qw(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbb ccccccccccccccccccccccc 2222222222222)],
1029 # use_blowfish => 'my_blowfish_key',
1033 =item auth_data (method)
1035 Contains authentication data stored during the get_valid_auth method.
1036 The data is normally blessed into the CGI::Ex::Auth::Data package which
1037 evaluates to false if there was an error and true if the authentication
1038 was successful - so this data can be defined but false.
1040 See the get_valid_auth method.
1042 =item base_dir_abs (method)
1044 Used as the absolute base directory to find template files and validation files.
1045 It may return a single value or an arrayref of values, or a coderef that
1046 returns an arrayref or coderef of values. You may pass base_dir_abs
1047 as a parameter in the arguments passed to the "new" method.
1049 Default value is "".
1051 For example, to pass multiple paths, you would use something
1052 similar to the following:
1055 return ['/my/path/one', '/some/other/path'];
1058 The base_dir_abs value is used along with the base_dir_rel, name_module,
1059 name_step, ext_print and ext_values for determining the values
1060 returned by the default file_print and file_val hooks. See those methods
1061 for further discussion.
1063 See the section on FINDING TEMPLATES for further discussion.
1065 =item base_dir_rel (method)
1067 Added as a relative base directory to content under the base_dir_abs directory.
1069 Default value is "".
1071 The base_dir_abs method is used as top level where template includes may
1072 pull from, while the base_dir_rel is directory relative to the base_dir_abs
1073 where the content files will be stored.
1075 A value for base_dir_rel may passed as a parameter in the arguments passed
1078 See the base_dir_abs method for more discussion.
1080 See the section on FINDING TEMPLATES for further discussion.
1082 =item cleanup_user (method)
1084 Used as a hook during get_valid_auth. Allows for cleaning
1085 up the username. See the get_valid_auth method.
1088 my ($self, $user) = @_;
1092 =item clear_app (method)
1094 If the same CGI::Ex::App based object is used to run multiple
1095 navigate sessions, the clear_app method should be called which
1096 will attempt to clear as much session information as it can.
1097 The following items will be cleared:
1107 __morph_lineage_start_index
1114 =item current_step (method)
1116 Returns the current step that the nav_loop is functioning on.
1118 =item default_step (method)
1120 Step to show if the path runs out of steps. Default value is the
1121 'default_step' property which defaults to 'main'.
1123 If nav_loop runs of the end of the path (runs out of steps), this
1124 method is called, the step is added to the path, and nav_loop calls
1127 =item destroy (method)
1129 Called at the end of navigate after all other actions have run. Can
1130 be used for undoing things done in the ->init method called during
1133 =item dump_history (method)
1135 Show simplified trace information of which steps were called, the
1136 order they were called in, the time they took to run, and a brief list
1137 of the output (to see the full response returned by each hook, pass a
1138 true value as the only argument to dump_history -
1139 $self->dump_history(1)). Indentation is also applied to show which
1140 hooks called other hooks.
1143 The first line shows the amount of time elapsed for the entire
1144 navigate execution. Subsequent lines contain:
1146 Step - the name of the current step.
1147 Hook - the name of the hook being called.
1148 Found - the name of the method that was found.
1149 Time - the total elapsed seconds that method took to run.
1150 Output - the response of the hook - shown in shortened form.
1152 Note - to get full output responses - pass a true value to
1153 dump_history - or just call ->history. Times displayed are to 5
1154 decimal places - this accuracy can only be provided if the Time::HiRes
1155 module is installed on your system (it will only be used if installed).
1157 It is usually best to print this history during the post_navigate
1158 method as in the following:
1160 use CGI::Ex::Dump qw(debug);
1161 sub post_navigate { debug shift->dump_history }
1163 The following is a sample output of dump_history called from the
1164 sample recipe application at the end of this document. The step
1167 debug: admin/Recipe.pm line 14
1168 shift->dump_history = [
1170 "view - run_step - run_step - 0.00488 - 1",
1171 " view - pre_step - pre_step - 0.00003 - 0",
1172 " view - skip - view_skip - 0.00004 - 0",
1173 " view - prepare - prepare - 0.00003 - 1",
1174 " view - info_complete - info_complete - 0.00010 - 0",
1175 " view - ready_validate - ready_validate - 0.00004 - 0",
1176 " view - prepared_print - prepared_print - 0.00441 - 1",
1177 " view - hash_base - hash_base - 0.00009 - HASH(0x84ea6ac)",
1178 " view - hash_common - view_hash_common - 0.00148 - HASH(0x8310a20)",
1179 " view - hash_form - hash_form - 0.00004 - HASH(0x84eaa78)",
1180 " view - hash_fill - hash_fill - 0.00003 - {}",
1181 " view - hash_swap - hash_swap - 0.00003 - {}",
1182 " view - hash_errors - hash_errors - 0.00003 - {}",
1183 " view - print - print - 0.00236 - 1",
1184 " view - file_print - file_print - 0.00024 - recipe/view.html",
1185 " view - name_module - name_module - 0.00007 - recipe",
1186 " view - name_step - name_step - 0.00004 - view",
1187 " view - swap_template - swap_template - 0.00161 - <html> ...",
1188 " view - template_args - template_args - 0.00008 - HASH(0x865abf8)",
1189 " view - fill_template - fill_template - 0.00018 - 1",
1190 " view - fill_args - fill_args - 0.00003 - {}",
1191 " view - print_out - print_out - 0.00015 - 1",
1192 " view - post_print - post_print - 0.00003 - 0"
1195 =item exit_nav_loop (method)
1197 This method should not normally used but there is no problem with
1198 using it on a regular basis. Essentially it is a "goto" that allows
1199 for a long jump to the end of all nav_loops (even if they are
1200 recursively nested). This effectively short circuits all remaining
1201 hooks for the current and remaining steps. It is used to allow the
1202 ->jump functionality. If the application has morphed, it will be
1203 unmorphed before returning. Also - the post_navigate method will
1206 =item ext_print (method)
1208 Added as suffix to "name_step" during the default file_print hook.
1210 Default value is 'html'.
1212 For example, if name_step returns "foo" and ext_print returns "html"
1213 then the file "foo.html" will be searched for.
1215 See the section on FINDING TEMPLATES for further discussion.
1217 =item ext_val (method)
1219 Added as suffix to "name_step" during the default file_val hook.
1221 Default value is 'val'.
1223 For example, if name_step returns "foo" and ext_val returns "val"
1224 then the file "foo.val" will be searched for.
1226 See the section on FINDING TEMPLATES for further discussion.
1228 =item first_step (method)
1230 Returns the first step of the path. Note that first_step may not be the same
1231 thing as default_step if the path was overridden.
1235 Returns a hashref of the items passed to the CGI. Returns
1236 $self->{form} which defaults to CGI::Ex::get_form.
1238 =item handle_error (method)
1240 If anything dies during execution, handle_error will be called with
1241 the error that had happened. Default action is to die with that error.
1243 =item history (method)
1245 Returns an arrayref which contains trace history of which hooks of
1246 which steps were ran. Useful for seeing what happened. In general -
1247 each line of the history will show the current step, the hook
1248 requested, and which hook was actually called.
1250 The dump_history method shows a short condensed version of this
1251 history which makes it easier to see what path was followed.
1253 In general, the arrayref is free for anything to push onto which will
1254 help in tracking other occurrences in the program as well.
1258 Called by the default new method. Allows for any object
1259 initilizations that may need to take place. Default action does
1262 =item fill_args (hook)
1264 Returns a hashref of args that will be passed to the CGI::Ex::Fill::fill.
1265 It is augmented with the template to swap and the fill hash. This
1266 could be useful if you needed to only swap a particular form on the template
1267 page. Arguments are passed directly to the fill function.
1269 sub fill_args { {target => 'my_form'} }
1271 =item fill_template (hook)
1273 Arguments are a template and a hashref. Takes the template that was
1274 prepared using swap_template, and swaps html form fields using the
1275 passed hashref. Overriding this method can control the fill behavior.
1277 Calls the fill_args hook prior to calling CGI::Ex::Fill::fill
1279 =item file_print (hook)
1281 Returns a filename of the content to be used in the default print
1282 hook. Adds method base_dir_rel to hook name_module, and name_step and
1283 adds on the default file extension found in $self->ext_print which
1284 defaults to the property $self->{ext_print} which will default to
1285 ".html". Should return a filename relative to base_dir_abs that can be
1286 swapped using CGI::Ex::Template, or should be a scalar reference to
1287 the template content that can be swapped. This will be used by the
1290 sub base_dir_abs { '/var/www/templates' }
1291 sub base_dir_rel { 'content' }
1292 sub name_module { 'recipe' }
1293 sub ext_print { 'html' } # default
1295 # ->file_print('this_step')
1296 # would return 'content/recipe/this_step.html'
1297 # the template engine would look in '/var/www/templates'
1298 # for a file by that name
1300 It may also return a reference to a string containing the html template.
1301 This is useful for prototyping applications and/or keeping all of
1302 the data for the application in a single location.
1304 =item file_val (hook)
1306 Returns a filename containing the validation. Performs the same
1307 as file_print, but uses ext_val to get the extension, and it adds
1308 base_dir_abs onto the returned value (file_print is relative to
1309 base_dir_abs, while file_val is fully qualified with base_dir_abs).
1310 If base_dir_abs returns an arrayref of paths, then each path is
1311 checked for the existence of the file.
1313 The file should be readable by CGI::Ex::Validate::get_validation.
1315 This hook is only necessary if the hash_validation hook has not been
1318 This method an also return a hashref containing the validation - but
1319 then you may have wanted to override the hash_validation hook.
1321 =item finalize (hook)
1323 Defaults to true. Used to do whatever needs to be done with the data once
1324 prepare has returned true and info_complete has returned true. On failure
1325 the print operations are ran. On success navigation moves on to the next
1328 This is normally were there core logic of a script will occur (such as
1329 adding to a database, or updating a record). At this point, the data
1330 should be validated. It is possible to do additional validation
1331 and return errors using code such as the following.
1333 if (! $user_is_unique) {
1334 $self->add_errors(username => 'The username was already used');
1338 =item find_hook (method)
1340 Called by run_hook. Arguments are a hook name, a step name. It
1341 should return an arrayref containing the code_ref to run, and the
1342 name of the method looked for. It uses ->can to find the appropriate
1345 my $code = $self->hook('finalize', 'main');
1346 ### will look first for $self->main_finalize;
1347 ### will then look for $self->finalize;
1349 This system is used to allow for multiple steps to be in the same
1350 file and still allow for moving some steps out to external sub classed
1351 packages (if desired).
1353 If the application has successfully morphed via the morph method and
1354 allow_morph then it is not necessary to add the step name to the
1355 beginning of the method name as the morphed packages method will
1356 override the base package (it is still OK to use the full method name
1357 "${step}_hookname").
1359 See the run_hook method and the morph method for more details.
1361 =item forbidden_step (method)
1363 Defaults to "__forbidden". The name of a step to run should the current
1364 step name be invalid, or if a step found by the default path method
1365 is invalid. See the path method.
1367 =item form_name (hook)
1369 Return the name of the form to attach the js validation to. Used by
1372 =item get_pass_by_user (method)
1374 This method is passed a username and the authentication object. It
1375 should return the password for the given user. See the get_pass_by_user
1376 method of CGI::Ex::Auth for more information. Installed as a hook
1377 to the authentication object during the get_valid_auth method.
1379 =item get_valid_auth (method)
1381 If require_auth is true at either the application level or at the
1382 step level, get_valid_auth will be called.
1384 It will call auth_args to get some default args to pass to
1385 CGI::Ex::Auth->new. It augments the args with sensible defaults that
1386 App already provides (such as form, cookies, and template facilities).
1387 It also installs hooks for the get_pass_by_user, cleanup_user, and verify_user
1388 hooks of CGI::Ex::Auth.
1390 It stores the $auth->last_auth_data in $self->auth_data for later use. For
1391 example, to get the authenticated user:
1393 sub require_auth { 1 }
1396 my ($self, $user) = @_;
1400 sub get_pass_by_user {
1401 my ($self, $user) = @_;
1402 my $pass = $self->some_method_to_get_the_pass($user);
1408 login_header => '<h1>My login header</h1>',
1409 login_footer => '[% TRY %][% INCLUDE login/login_footer.htm %][% CATCH %]<!-- [% error %] -->[% END %]',
1413 sub main_hash_swap {
1415 my $user = $self->auth_data->{'user'};
1416 return {user => $user};
1419 Successful authentication is cached for the duration of the
1420 nav_loop so multiple steps will run the full authentication routine
1423 Full customization of the login process and the login template can
1424 be done via the auth_args hash. See the auth_args method and
1425 CGI::Ex::Auth perldoc for more information.
1427 =item hash_base (hook)
1429 A hash of base items to be merged with hash_form - such as pulldown
1430 menus, javascript validation, etc. It will now also be merged with
1431 hash_fill, so it can contain default fillins as well. It can be
1432 populated by passing a hash to ->add_to_base. By default a sub
1433 similar to the following is what is used for hash_common. Note the
1434 use of values that are code refs - so that the js_validation and
1435 form_name hooks are only called if requested:
1438 my ($self, $step) = @_;
1439 return $self->{hash_base} ||= {
1440 script_name => $ENV{SCRIPT_NAME},
1441 js_validation => sub { $self->run_hook('js_validation', $step) },
1442 form_name => sub { $self->run_hook('form_name', $step) },
1446 =item hash_common (hook)
1448 Almost identical in function and purpose to hash_base. It is
1449 intended that hash_base be used for common items used in various
1450 scripts inheriting from a common CGI::Ex::App type parent. Hash_common
1451 is more intended for step level populating of both swap and fill.
1453 =item hash_errors (hook)
1455 Called in preparation for print after failed prepare, info_complete,
1456 or finalize. Should contain a hash of any errors that occurred. Will
1457 be merged into hash_form before the pass to print. Each error that
1458 occurred will be passed to method format_error before being added to
1459 the hash. If an error has occurred, the default validate will
1460 automatically add {has_errors =>1}. To the error hash at the time of
1461 validation. has_errors will also be added during the merge in case the
1462 default validate was not used. Can be populated by passing a hash to
1463 ->add_to_errors or ->add_errors.
1465 =item hash_fill (hook)
1467 Called in preparation for print after failed prepare, info_complete,
1468 or finalize. Should contain a hash of any items needed to be filled
1469 into the html form during print. Items from hash_form, hash_base, and
1470 hash_common will be layered together. Can be populated by passing a
1471 hash to ->add_to_fill.
1473 By default - forms are sticky and data from previous requests will try
1474 and populate the form. You can use the fill_template hook to disable
1475 templating on a single page or on all pages.
1477 This method can be used to pre-populate the form as well (such as on an
1478 edit step). If a form fails validation, hash_fill will also be called
1479 and will only want the submitted form fields to be sticky. You can
1480 use the ready_validate hook to prevent pre-population in these cases as
1483 sub edit_hash_fill {
1486 return {} if $self->run_hook('ready_validate', $step);
1490 ### get previous values from the database
1495 =item hash_form (hook)
1497 Called in preparation for print after failed prepare, info_complete,
1498 or finalize. Defaults to ->form. Can be populated by passing a hash
1501 =item hash_swap (hook)
1503 Called in preparation for print after failed prepare, info_complete,
1504 or finalize. Should contain a hash of any items needed to be swapped
1505 into the html during print. Will be merged with hash_base,
1506 hash_common, hash_form, and hash_errors. Can be populated by passing
1507 a hash to ->add_to_swap.
1509 The hash will be passed as the second argument to swap_template.
1511 =item hash_validation (hook)
1513 Returns a hash of the validation information to check form against.
1514 By default, will look for a filename using the hook file_val and will
1515 pass it to CGI::Ex::Validate::get_validation. If no file_val is
1516 returned or if the get_validation fails, an empty hash will be returned.
1517 Validation is implemented by ->vob which loads a CGI::Ex::Validate object.
1519 =item info_complete (hook)
1521 Calls the ready_validate hook to see if data is ready to validate. If
1522 so it calls the validate hook to validate the data. Should make
1523 sure the data is ready and valid. Will not be run unless
1524 prepare returns true (default).
1526 =item insert_path (method)
1528 Arguments are the steps to insert. Can be called any time. Inserts
1529 the new steps at the current path location.
1531 =item is_authed (method)
1533 Returns true if the object has successful authentication data. It
1534 returns false if the object has not been authenticated.
1536 =item js_uri_path (method)
1538 Return the URI path where the CGI/Ex/yaml_load.js and
1539 CGI/Ex/validate.js files can be found. This will default to
1540 "$ENV{SCRIPT_NAME}/js" if the path method has not been overridden,
1541 otherwise it will default to "$ENV{SCRIPT_NAME}?step=js&js=" (the
1542 latter is more friendly with overridden paths). A default handler for
1543 the "js" step has been provided in "js_run_step" (this handler will
1544 nicely print out the javascript found in the js files which are
1545 included with this distribution. js_run_step will work properly with the
1546 default "path" handler.
1548 =item js_validation (hook)
1550 Requires JSON or YAML. Will return Javascript that is capable of
1551 validating the form. This is done using the capabilities of
1552 CGI::Ex::Validate. This will call the hook hash_validation which will
1553 then be encoded either json or into yaml and placed in a javascript
1554 string. It will also call the hook form_name to determine which html
1555 form to attach the validation to. The method js_uri_path is called to
1556 determine the path to the appropriate validate.js files. If the
1557 method ext_val is htm, then js_validation will return an empty string
1558 as it assumes the htm file will take care of the validation itself.
1559 In order to make use of js_validation, it must be added to the
1560 variables returned by either the hash_base, hash_common, hash_swap or
1561 hash_form hook (see examples of hash_base used in this doc).
1563 By default it will try and use JSON first and then fail to YAML and
1564 then will fail to returning an html comment that does nothing.
1568 This method should not normally be used but is fine to use it on a
1569 regular basis. It provides for moving to the next step at any point
1570 during the nav_loop. It effectively short circuits the remaining
1571 hooks for the current step. It does increment the recursion counter
1572 (which has a limit of ->recurse_limit - default 15). It is normally
1573 better to allow the other hooks in the loop to carry on their normal
1574 functions and avoid jumping. (Essentially, this hook behaves like a
1575 goto method to bypass everything else and continue at a different
1576 location in the path - there are times when it is necessary or useful
1579 Jump takes a single argument which is the location in the path to jump
1580 to. This argument may be either a step name, the special strings
1581 "FIRST, LAST, CURRENT, PREVIOUS, OR NEXT" or the number of steps to
1582 jump forward (or backward) in the path. The default value, 1,
1583 indicates that CGI::Ex::App should jump to the next step (the default
1584 action for jump). A value of 0 would repeat the current step (watch
1585 out for recursion). A value of -1 would jump to the previous step.
1586 The special value of "LAST" will jump to the last step. The special
1587 value of "FIRST" will jump back to the first step. In each of these
1588 cases, the path array returned by ->path is modified to allow for the
1589 jumping (the path is modified so that the path history is not destroyed
1590 - if we were on step 3 and jumped to one, that path would contain
1591 1, 2, 3, *1, 2, 3, 4, etc and we would be at the *).
1593 ### goto previous step
1594 $self->jump($self->previous_step);
1595 $self->jump('PREVIOUS');
1599 $self->jump($self->next_step);
1600 $self->jump('NEXT');
1604 ### goto current step (repeat)
1605 $self->jump($self->current_step);
1606 $self->jump('CURRENT');
1610 $self->jump($self->last_step);
1611 $self->jump('LAST');
1614 $self->jump($self->first_step);
1615 $self->jump('FIRST');
1617 =item last_step (method)
1619 Returns the last step of the path. Can be used to jump to the last step.
1621 =item morph (method)
1623 Allows for temporarily "becoming" another object type for the
1624 execution of the current step. This allows for separating some steps
1625 out into their own packages.
1627 Morph will only run if the method allow_morph returns true.
1628 Additionally if the allow_morph returns a hash ref, morph will only
1629 run if the step being morphed to is in the hash. Morph also passes
1630 the step name to allow_morph.
1632 The morph call occurs at the beginning of the step loop. A
1633 corresponding unmorph call occurs before the loop is exited. An
1634 object can morph several levels deep if allow_nested_morph returns
1635 true. For example, an object running as Foo::Bar that is looping on
1636 the step "my_step" that has allow_morph = 1, will do the following:
1638 Call the morph_package hook (which would default to returning
1639 Foo::Bar::MyStep in this case)
1641 Translate this to a package filename (Foo/Bar/MyStep.pm) and try
1642 and require it, if the file can be required, the object is blessed
1645 Call the fixup_after_morph method.
1647 Continue on with the run_step for the current step.
1649 At any exit point of the loop, the unmorph call is made which
1650 re-blesses the object into the original package.
1652 Samples of allowing morph:
1654 sub allow_morph { 1 }
1656 sub allow_morph { {edit => 1} }
1658 sub allow_morph { my ($self, $step) = @_; return $step eq 'edit' }
1660 It is possible to call morph earlier on in the program. An example of
1661 a useful early use of morph would be as in the following code:
1663 sub allow_morph { 1 }
1667 if ($ENV{'PATH_INFO'} && $ENV{'PATH_INFO'} =~ s|^/(\w+)||) {
1669 $self->morph($step);
1670 $ENV{'PATH_INFO'} = "/$step";
1671 $self->stash->{'base_morphed'} = 1;
1678 $self->unmorph if $self->stash->{'base_morphed'};
1681 If this code was in a module Base.pm and the cgi running was cgi/base
1686 and you created a sub module that inherited Base.pm called
1687 Base/Ball.pm -- you could then access it using cgi/base/ball. You
1688 would be able to pass it steps using either cgi/base/ball/step_name or
1689 cgi/base/ball?step=step_name - Or Base/Ball.pm could implement its
1690 own path. It should be noted that if you do an early morph, it is
1691 suggested to provide a call to unmorph. And if you want to let your
1692 early morphed object morph again - you will need to provide
1694 sub allow_nested_morph { 1 }
1696 With allow_nested_morph enabled you could create the file
1697 Base/Ball/StepName.pm which inherits Base/Ball.pm. The Base.pm, with
1698 the custom init and default path method, would automatically morph us
1699 first into a Base::Ball object (during init) and then into a
1700 Base::Ball::StepName object (during the navigation loop).
1702 Since it is complicated to explain - it may be a bit complicated to
1703 those who will try to follow your code later. CGI::Ex::App provides
1704 many ways to do things, but use the best one for your situation.
1706 =item morph_package (hook)
1708 Used by morph. Return the package name to morph into during a morph
1709 call. Defaults to using the current object type as a base. For
1710 example, if the current object running is a Foo::Bar object and the
1711 step running is my_step, then morph_package will return
1714 Because of the way that run_hook works, it is possible that several
1715 steps could be located in the same external file and overriding morph_package
1716 could allow for this to happen.
1718 See the morph method.
1720 =item name_module (hook)
1722 Return the name (relative path) that should be pre-pended to name_step
1723 during the default file_print and file_val lookups. Defaults to
1724 the value in $self->{name_module} which in turn defaults to the name
1725 of the current script.
1727 cgi-bin/my_app.pl => my_app
1728 cgi/my_app => my_app
1730 This method is provided so that each cgi or mod_perl application can
1731 have its own directory for storing html for its steps.
1733 See the file_print method for more information.
1735 See the section on FINDING TEMPLATES for further discussion.
1737 =item name_step (hook)
1739 Return the step (appended to name_module) that should used when
1740 looking up the file in file_print and file_val lookups. Defaults to
1743 See the section on FINDING TEMPLATES for further discussion.
1745 =item nav_loop (method)
1747 This is the main loop runner. It figures out the current path
1748 and runs all of the appropriate hooks for each step of the path. If
1749 nav_loop runs out of steps to run (which happens if no path is set, or if
1750 all other steps run successfully), it will insert the ->default_step into
1751 the path and run nav_loop again (recursively). This way a step is always
1752 assured to run. There is a method ->recurse_limit (default 15) that
1753 will catch logic errors (such as inadvertently running the same
1754 step over and over and over because there is either no hash_validation,
1755 or the data is valid but the set_ready_validate(0) method was not called).
1757 =item navigate (method)
1759 Takes a class name or a CGI::Ex::App object as arguments. If a class
1760 name is given it will call the "new" method to instantiate an object
1761 by that class (passing any extra arguments to the new method). All
1762 returns from navigate will return the object.
1764 The method navigate is essentially a safe wrapper around the ->nav_loop
1765 method. It will catch any dies and pass them to ->handle_error.
1767 This starts the process flow for the path and its steps.
1769 =item navigate_authenticated (method)
1771 Same as the method navigate but sets require_auth(1) before
1772 running. See the require_auth method.
1774 =item new (class method)
1776 Object creator. Takes a hashref of arguments that will become the
1777 initial properties of the object. Calls the init method once the
1778 object has been blessed to allow for any other initilizations.
1780 my $app = MyApp->new({name_module => 'my_app'});
1782 =item next_step (hook and method)
1784 Returns the next step in the path. If there is no next step, it
1785 returns the default_step.
1787 It can be used as a method to return the next step in the path
1788 to pass to a method such as ->jump.
1790 It is also used as a hook by the refine_path hook. If there is no
1791 more steps, it will call the next_step hook to try and find a step to
1796 Return an arrayref (modifiable) of the steps in the path. For each
1797 step the run_step hook and all of its remaining hooks will be run.
1799 Hook methods are looked up and ran using the method "run_hook" which
1800 uses the method "find_hook" to lookup the hook. A history of ran
1801 hooks is stored in the array ref returned by $self->history.
1803 If path has not been defined, the method will look first in the form
1804 for a key by the name found in ->step_key. It will then look in
1805 $ENV{'PATH_INFO'}. It will use this step to create a path with that
1806 one step as its contents. If a step is passed in via either of these
1807 ways, the method will call valid_steps to make sure that the step
1808 is valid (by default valid_steps returns undef - which means that
1809 any step is valid). Any step beginning with _ can not be passed in
1810 and are intended for use on private paths. If a non-valid step is
1811 found, then path will be set to contain a single step of ->forbidden_step.
1813 For the best functionality, the arrayref returned should be the same
1814 reference returned for every call to path - this ensures that other
1815 methods can add to the path (and will most likely break if the
1816 arrayref is not the same).
1818 If navigation runs out of steps to run, the default step found in
1819 default_step will be run. This is what allows for us to default
1820 to the "main" step for many applications.
1822 =item path_info_map (hook)
1824 Used to map path_info parts to form variables. Similar to the
1825 path_info_map_base method. See the path_info_map_base method
1826 for a discussion of how to use this hook.
1828 =item path_info_map_base (method)
1830 Called during the default path method. It is used to custom map portions
1831 of $ENV{'PATH_INFO'} to form values. If should return an arrayref of
1832 arrayrefs where each child arrayref contains a regex qr with match parens
1833 as the first element of the array. Subsequent elements of the array are
1834 the key names to store the corresponding matched value from the regex under.
1835 The outer arrayref is iterated until it one of child arrayrefs matches
1836 against $ENV{'PATH_INFO'}. The matched values are only added to the form if
1837 there is not already a defined value for that key in the form.
1839 The default value returned by this method looks something like the following:
1841 sub path_info_map_base {
1842 return [[qr{^/(\w+)}, $self->step_key]];
1845 This example would map the following PATH_INFO string as follows:
1849 # $self->form->{'step'} now equals "my_step"
1851 The following is another example:
1853 sub path_info_map_base {
1855 [qr{^/([^/]+)/(\w+)}, 'username', $self->step_key],
1856 [qr{^/(\w+)}, $self->step_key],
1860 # the PATH_INFO /my_step
1862 # $self->form->{'step'} now equals "my_step"
1864 # but with the PATH_INFO /my_user/my_step
1865 # $self->form->{'step'} now equals "my_step"
1866 # and $self->form->{'username'} equals "my_user"
1868 In most cases there is not a need to override the path_info_map_base
1869 method, but rather override the path_info_map hook for a particular step.
1870 When the step is being run, just before the run_step hook is called, the
1871 path_info_map hook is called. The path_info_map hook is similar to
1872 the path_info_map_base method, but is used to allow step level manipulation
1873 of form based on elements in the $ENV{'PATH_INFO'}.
1875 sub my_step_path_info_map {
1876 return [[qr{^/my_step/(\w+)$}, 'username']];
1879 # the PATH_INFO /my_step/my_user
1881 # $self->form->{'step'} equal to "my_step" because of default path_info_map_base
1882 # and $self->form->{'username'} equals "my_user" because of my_step_path_info_map
1884 The section on mapping URIs to steps has additional examples.
1886 =item post_loop (method)
1888 Ran after all of the steps in the loop have been processed (if
1889 prepare, info_complete, and finalize were true for each of the steps).
1890 If it returns a true value the navigation loop will be aborted. If it
1891 does not return true, navigation continues by then inserting the step
1892 $self->default_step and running $self->nav_loop again (recurses) to
1893 fall back to the default step.
1895 =item post_navigate (method)
1897 Called from within navigate. Called after the nav_loop has finished
1898 running but within the eval block to catch errors. Will only run if
1899 there were no errors which died during the nav_loop process.
1901 It can be disabled from running by setting the _no_post_navigate
1904 If per-step authentication is enabled and authentication fails,
1905 the post_navigate method will still be called (the post_navigate
1906 method can check the ->is_authed method to change behavior). If
1907 application level authentication is enabled and authentication
1908 fails, none of the pre_navigate, nav_loop, or post_navigate methods
1911 =item post_print (hook)
1913 A hook which occurs after the printing has taken place. Is only run
1914 if the information was not complete. Useful for cases such as
1915 printing rows of a database query after displaying a query form.
1917 =item post_step (hook)
1919 Ran at the end of the step's loop if prepare, info_complete, and
1920 finalize all returned true. Allows for cleanup. If a true value is
1921 returned, execution of navigate is returned and no more steps are
1924 =item pre_loop (method)
1926 Called right before the navigation loop is started (at the beginning
1927 of nav_loop). At this point the path is set (but could be modified).
1928 The only argument is a reference to the path array. If it returns a
1929 true value - the navigation routine is aborted.
1931 =item pre_navigate (method)
1933 Called at the very beginning of the navigate method, but within the
1934 eval block to catch errors. Called before the nav_loop method is
1935 started. If a true value is returned then navigation is skipped (the
1936 nav_loop is never started).
1938 =item pre_step (hook)
1940 Ran at the beginning of the loop before prepare, info_compelete, and
1941 finalize are called. If it returns true, execution of nav_loop is
1942 returned and no more steps are processed..
1944 =item prepare (hook)
1946 Defaults to true. A hook before checking if the info_complete is true.
1947 Intended to be used to cleanup the form data.
1949 =item prepared_print (hook)
1951 Called when any of prepare, info_complete, or finalize fail. Prepares
1952 a form hash and a fill hash to pass to print. The form hash is primarily
1953 intended for use by the templating system. The fill hash is intended
1954 to be used to fill in any html forms.
1956 =item previous_step (method)
1958 List the step previous to this one. Will return '' if there is no previous step.
1962 Take the information generated by prepared_print, format it, and print it out.
1963 Default incarnation uses CGI::Ex::Template which is compatible with
1964 Template::Toolkit. Arguments are: step name (used to call the
1965 file_print hook), swap hashref (passed to call swap_template), and
1966 fill hashref (passed to fill_template).
1968 During the print call, the file_print hook is called which should
1969 return a filename or a scalar reference to the template content is
1971 =item ready_validate (hook)
1973 Should return true if enough information is present to run validate.
1974 Default is to look if $ENV{'REQUEST_METHOD'} is 'POST'. A common
1975 usage is to pass a common flag in the form such as 'processing' => 1
1976 and check for its presence - such as the following:
1978 sub ready_validate { shift->form->{'processing'} }
1980 Changing the behavior of ready_validate can help in making wizard type
1983 =item refine_path (hook)
1985 Called at the end of nav_loop. Passed a single value indicating
1986 if there are currently more steps in the path.
1988 The default implementation returns if there are still more steps
1989 in the path. Otherwise, it calls the next_step hook and appends
1990 it to the path with the append_path method, and then calls
1991 the set_ready_validate hook and passes it 0.
1993 This allows you to simply put
1995 sub edit_next_step { '_edit_success' }
1997 In your code and it will automatically do the right thing and
1998 go to the _edit_success step.
2000 =item recurse_limit (method)
2002 Default 15. Maximum number of times to allow nav_loop to call itself.
2003 The recurse level will increase every time that ->jump is called, or if
2004 the end of the nav_loop is reached and the process tries to add the
2005 default_step and run it again.
2007 If ->jump is used often - the recurse_limit will be reached more
2008 quickly. It is safe to raise this as high as is necessary - so long
2009 as it is intentional.
2011 Often the limit is reached if a step did not have a validation hash,
2012 or if the set_ready_validate(0) method was not called once the data
2013 had been successfully validated and acted upon.
2015 =item replace_path (method)
2017 Arguments are the steps used to replace. Can be called any time.
2018 Replaces the remaining steps (if any) of the current path.
2020 =item require_auth (method)
2022 Default undef. Can return either a true value or a hashref of step names.
2024 If a hashref of stepnames is returned, authentication will be turned on
2025 at the step level. In this mode if any step is accessed, the get_valid_auth
2026 method will be called. If it fails, then the nav_loop will be stopped
2027 (the post_navigate method will be called - use the is_authed method to perform
2028 different functions). Any step of the path not in the hash will not require
2029 authentication. For example, to add authentication to add authentication
2030 to the add, edit and delete steps you could do:
2032 sub require_auth { {add => 1, edit => 1, delete => 1} }
2034 If a non-hash true value is returned from the require_auth method then
2035 authentication will take place before the pre_navigation or the nav_loop methods.
2036 If authentication fails the navigation process is exited (the post_navigate
2037 method will not be called).
2039 sub require_auth { 1 }
2041 Alternatively you can also could do either of the following:
2043 __PACKAGE__->navigate_authenticated; # instead of __PACKAGE__->navigate;
2047 sub init { shift->require_auth(1) }
2051 __PACKAGE__->new({require_auth => 1}->navigate;
2053 If get_valid_auth returns true, in either case, the is_authed method will
2054 return true and the auth_data will contain the authenticated user's data.
2055 If it returns false, auth_data may possibly contain a defined but false
2056 data object with details as to why authentication failed.
2058 See the get_valid_auth method.
2060 =item run_hook (method)
2062 Arguments are a hook name and the step to find the hook for. Calls
2063 the find_hook method to get a code ref which it then calls and returns
2064 the result passing any extra arguments to run_hook as arguments to the
2067 Each call to run_hook is logged in the arrayref returned by the
2068 history method. This information is summarized in the dump_history
2069 method and is useful for tracing the flow of the program.
2071 The run_hook method is part of the core of CGI::Ex::App. It allows
2072 for an intermediate layer in normal method calls. Because of
2073 run_hook, it is possible to logically override methods on a step by
2074 step basis, or override a method for all of the steps, or even to
2075 break code out into separate modules.
2077 =item run_step (hook)
2079 Runs all of the hooks specific to each step, beginning with pre_step
2080 and ending with post_step (for a full listing of steps, see the
2081 section on process flow). Called after ->morph($step) has been run.
2082 If this hook returns true, the nav_loop is exited (meaning the
2083 run_step hook displayed a printed page). If it returns false, the
2084 nav_loop continues on to run the next step.
2086 This hook performs the same base functionality as a method defined in
2087 CGI::Applications ->run_modes. The default run_step method provides
2088 much more granular control over the flow of the CGI.
2090 =item set_path (method)
2092 Arguments are the steps to set. Should be called before navigation
2093 begins. This will set the path arrayref to the passed steps.
2095 This method is not normally used.
2097 =item set_ready_validate (hook and method)
2099 Sets that the validation is ready (or not) to validate. Should set the value
2100 checked by the hook ready_validate. The following would complement the
2101 processing flag above:
2103 sub set_ready_validate {
2105 my ($step, $is_ready) = (@_ == 2) ? @_ : (undef, shift);
2107 $self->form->{'processing'} = 1;
2109 delete $self->form->{'processing'};
2114 Note that for this example the form key "processing" was deleted. This
2115 is so that the call to fill in any html forms won't swap in a value of
2116 zero for form elements named "processing."
2118 Also note that this method may be called as a hook as in
2120 $self->run_hook('set_ready_validate', $step, 0)
2122 $self->set_ready_validate($step, 0);
2124 Or it can take a single argument and should set the ready status
2125 regardless of the step as in:
2127 $self->set_ready_validate(0);
2131 Ran at the beginning of the loop before prepare, info_complete, and
2132 finalize are called. If it returns true, nav_loop moves on to the
2133 next step (the current step is skipped).
2135 =item stash (method)
2137 Returns a hashref that can store arbitrary user space data without
2138 worrying about overwriting the internals of the application.
2140 =item step_key (method)
2142 Should return the keyname that will be used by the default "path"
2143 method to look for in the form. Default value is 'step'.
2145 =item swap_template (hook)
2147 Takes the template and hash of variables prepared in print, and processes them
2148 through the current template engine (default engine is CGI::Ex::Template).
2150 Arguments are the template and the swap hashref. The template can be either a
2151 scalar reference to the actual content, or the filename of the content. If the
2152 filename is specified - it should be relative to base_dir_abs (which will be
2153 used to initialize INCLUDE_PATH by default).
2155 The default method will create a template object by calling the template_args hook
2156 and passing the returned hashref to the template_obj method. The default template_obj method
2157 returns a CGI::Ex::Template object, but could easily be swapped to use a Template::Toolkit
2158 based object. If a non-Template::Toolkit compatible object is to be used, then
2159 the swap_template hook can be overridden to use another templating engine.
2161 For example to use the HTML::Template engine you could override the swap_template
2167 my ($self, $step, $file, $swap) = @_;
2169 my $type = UNIVERSAL::isa($file, 'SCALAR') ? 'scalarref'
2170 : UNIVERSAL::isa($file, 'ARRAY') ? 'arrayref'
2171 : ref($file) ? 'filehandle'
2174 my $t = HTML::Template->new(source => $file,
2176 path => $self->base_dir_abs,
2177 die_on_bad_params => 0,
2185 As of version 2.13 of CGI::Ex::Template you could also simply do the
2186 following to parse the templates using HTML::Template::Expr syntax.
2189 return {SYNTAX => 'hte'};
2192 =item template_args (hook)
2194 Returns a hashref of args that will be passed to the "new" method of CGI::Ex::Template.
2195 The method is normally called from the swap_template hook. The swap_template hook
2196 will add a value for INCLUDE_PATH which is set equal to base_dir_abs, if the INCLUDE_PATH
2197 value is not already set.
2199 The returned hashref can contain any arguments that CGI::Ex::Template would understand.
2204 WRAPPER => 'wrappers/main_wrapper.html',
2208 =item template_obj (method)
2210 Called from swap_template. It is passed the result of template_args that have
2211 had a default INCLUDE_PATH added. The default implementation uses CGI::Ex::Template
2212 but can easily be changed to use Template::Toolkit by using code similar to the following:
2217 my ($self, $args) = @_;
2218 return Template->new($args);
2221 =item unmorph (method)
2223 Allows for returning an object back to its previous blessed state if
2224 the "morph" method was successful in morphing the App object. This
2225 only happens if the object was previously morphed into another object
2226 type. Before the object is re-blessed the method fixup_before_unmorph
2229 See allow_morph and morph.
2231 =item valid_steps (method)
2233 Called by the default path method. Should return a hashref of path
2234 steps that are allowed. If the current step is not found in the hash
2235 (or is not the default_step or js_step) the path method will return a
2236 single step of ->forbidden_step and run its hooks. If no hash or undef is
2237 returned, all paths are allowed (default). A key "forbidden_step"
2238 containing the step that was not valid will be placed in the stash.
2239 Often the valid_steps method does not need to be defined as arbitrary
2240 method calls are not possible with CGI::Ex::App.
2242 Any steps that begin with _ are also "not" valid for passing in via the form
2243 or path info. See the path method.
2245 Also, the pre_step, skip, prepare, and info_complete hooks allow for validating
2246 the data before running finalize.
2248 =item validate (hook)
2250 Passed the form from $self->form. Runs validation on the information
2251 contained in the passed form. Uses CGI::Ex::Validate for the default
2252 validation. Calls the hook hash_validation to load validation hashref
2253 (an empty hash means to pass validation). Should return true if the
2254 form passed validation and false otherwise. Errors are stored as a
2255 hash in $self->{hash_errors} via method add_errors and can be checked
2256 for at a later time with method has_errors (if the default validate
2259 There are many ways and types to validate the data. Please see the
2260 L<CGI::Ex::Validate> module.
2262 Upon success, it will look through all of the items which were
2263 validated, if any of them contain the keys append_path, insert_path,
2264 or replace_path, that method will be called with the value as
2265 arguments. This allows for the validation to apply redirection to the
2266 path. A validation item of:
2268 {field => 'foo', required => 1, append_path => ['bar', 'baz']}
2270 would append 'bar' and 'baz' to the path should all validation succeed.
2272 =item verify_user (method)
2274 Installed as a hook to CGI::Ex::App during get_valid_auth. Should return
2275 true if the user is ok. Default is to always return true. This can be
2276 used to abort early before the get_pass_by_user hook is called.
2279 my ($self, $user) = @_;
2280 return 0 if $user eq 'paul'; # don't let paul in
2281 return 1; # let anybody else in
2286 =head1 HOW DO I SET COOKIES, REDIRECT, ETC
2288 Often in your program you will want to set cookies or bounce to a differnt URL.
2289 This can be done using either the builtin CGI::Ex object or the built in
2290 CGI object. It is suggested that you only use the CGI::Ex methods as it will
2291 automatically send headers and method calls under cgi, mod_perl1, or mod_perl2.
2292 The following shows how to do basic items using the CGI::Ex object returned by
2297 =item printing content-type headers
2299 ### CGI::Ex::App prints headers for you,
2300 ### but if you are printing custom types, you can send your own
2301 $self->cgix->print_content_type;
2303 # $self->cgix->print_content_type('text/html');
2305 =item setting a cookie
2307 $self->cgix->set_cookie({
2309 -value => 'Some Value',
2314 =item redirecting to another URL
2316 $self->cgix->location_bounce("http://somewhereelse.com");
2317 $self->exit_nav_loop; # normally should do this to long jump out of navigation
2319 =item making a QUERY_STRING
2321 my $data = {foo => "bar", one => "two or three"};
2322 my $query = $self->cgix->make_form($data);
2323 # $query now equals "foo=bar&one=two%20or%20three"
2325 =item getting form parameters
2327 my $form = $self->form;
2329 In this example $form would now contain a hashref of all POST and GET parameters
2330 passed to the server. The form method calls $self->cgix->get_form
2331 which in turn uses CGI->param to parse values. Fields with multiple passed
2332 values will be in the form of an arrayref.
2334 =item getting cookies
2336 my $cookies = $self->cookies;
2338 In this example $cookies would be a hashref of all passed in cookies. The
2339 cookies method calls $self->cgix->get_cookies which in turn uses CGI->cookie
2344 See the CGI::Ex and CGI documentation for more information.
2346 =head1 COMPARISON TO OTHER APPLICATION MODULES
2348 The concepts used in CGI::Ex::App are not novel or unique. However, they
2349 are all commonly used and very useful. All application builders were
2350 built because somebody observed that there are common design patterns
2351 in CGI building. CGI::Ex::App differs in that it has found more common design
2352 patterns of CGI's than other application builders and tries to get in the way
2355 CGI::Ex::App is intended to be sub classed, and sub sub classed, and each step
2356 can choose to be sub classed or not. CGI::Ex::App tries to remain simple
2357 while still providing "more than one way to do it." It also tries to avoid
2358 making any sub classes have to call ->SUPER:: (although that is fine too).
2360 And if what you are doing on a particular is far too complicated or custom for
2361 what CGI::Ex::App provides, CGI::Ex::App makes it trivial to override all behavior.
2363 There are certainly other modules for building CGI applications. The
2364 following is a short list of other modules and how CGI::Ex::App is
2369 =item C<CGI::Application>
2371 Seemingly the most well know of application builders.
2372 CGI::Ex::App is different in that it:
2374 * Uses Template::Toolkit compatible CGI::Ex::Template by default
2375 CGI::Ex::App can easily use another toolkit by simply
2376 overriding the ->swap_template method.
2377 CGI::Application uses HTML::Template.
2378 * Offers integrated data validation.
2379 CGI::Application has had custom plugins created that
2380 add some of this functionality. CGI::Ex::App has the benefit
2381 that validation is automatically available in javascript as well.
2382 * Allows the user to print at any time (so long as proper headers
2383 are sent. CGI::Application requires data to be pipelined.
2384 * Offers hooks into the various phases of each step ("mode" in
2385 CGI::Application lingo). CGI::Application provides only ->runmode
2386 which is only a dispatch.
2387 * Support for easily jumping around in navigation steps.
2388 * Support for storing some steps in another package.
2389 * Integrated authentication
2390 * Integrated form filling
2391 * Integrated PATH_INFO mapping
2393 CGI::Ex::App and CGI::Application are similar in that they take care
2394 of handling headers and they allow for calling other "runmodes" from
2395 within any given runmode. CGI::Ex::App's ->run_step is essentially
2396 equivalent to a method call defined in CGI::Application's ->run_modes.
2397 The ->run method of CGI::Application starts the application in the same
2398 manner as CGI::Ex::App's ->navigate call. Many of the hooks around
2399 CGI::Ex::App's ->run_step call are similar in nature to those provided by
2402 =item C<CGI::Prototype>
2404 There are actually many similarities. One of the nicest things about
2405 CGI::Prototype is that it is extremely short (very very short). The
2406 ->activate starts the application in the same manner as CGI::Ex::App's
2407 ->navigate call. Both use Template::Toolkit as the default template
2408 system (CGI::Ex::App uses CGI::Ex::Template which is TT compatible).
2409 CGI::Ex::App is differrent in that it:
2411 * Offers more hooks into the various phases of each step.
2412 * Support for easily jumping around in navigation steps.
2413 * Support for storing only some steps in another package.
2414 * Integrated data validation
2415 * Integrated authentication
2416 * Integrated form filling
2417 * Integrated PATH_INFO mapping
2422 =head1 SIMPLE EXTENDED EXAMPLE
2424 The following example shows the creation of a basic recipe
2425 database. It requires the use of DBD::SQLite, but that is all.
2426 Once you have configured the db_file and base_dir_abs methods
2427 of the "recipe" file, you will have a working script that
2428 does CRUD for the recipe table. The observant reader may ask - why
2429 not use Catalyst or Ruby on Rails? The observant programmer will
2430 reply that making a framework do something simple is easy, but making
2431 it do something complex is complex and any framework that tries to
2432 do the those complex things for you is too complex. CGI::Ex::App
2433 lets you write the complex logic but gives you the ability to
2434 not worry about the boring details such as template engines,
2435 or sticky forms, or cgi parameters, or data validation. Once
2436 you are setup and are running, you are only left with providing
2437 the core logic of the application.
2439 ### File: /var/www/cgi-bin/recipe (depending upon Apache configuration)
2440 ### --------------------------------------------
2443 use lib qw(/var/www/lib);
2448 ### File: /var/www/lib/Recipe.pm
2449 ### --------------------------------------------
2453 use base qw(CGI::Ex::App);
2454 use CGI::Ex::Dump qw(debug);
2459 ###------------------------------------------###
2462 # show what happened
2463 debug shift->dump_history;
2466 sub base_dir_abs { '/var/www/templates' }
2468 sub base_dir_rel { 'content' }
2470 sub db_file { '/var/www/recipe.sqlite' }
2474 if (! $self->{'dbh'}) {
2475 my $file = $self->db_file;
2476 my $exists = -e $file;
2477 $self->{'dbh'} = DBI->connect("dbi:SQLite:dbname=$file", '', '',
2479 $self->create_tables if ! $exists;
2481 return $self->{'dbh'};
2487 $self->dbh->do("CREATE TABLE recipe (
2488 id INTEGER PRIMARY KEY AUTOINCREMENT,
2489 title VARCHAR(50) NOT NULL,
2490 ingredients VARCHAR(255) NOT NULL,
2491 directions VARCHAR(255) NOT NULL,
2492 date_added VARCHAR(20) NOT NULL
2496 ###----------------------------------------------------------------###
2498 sub main_info_complete { 0 }
2500 sub main_hash_swap {
2503 my $s = "SELECT id, title, date_added
2505 ORDER BY date_added";
2506 my $data = $self->dbh->selectall_arrayref($s);
2507 my @data = map {my %h; @h{qw(id title date_added)} = @$_; \%h} @$data;
2514 ###----------------------------------------------------------------###
2516 sub add_name_step { 'edit' }
2518 sub add_hash_validation {
2520 'group order' => [qw(title ingredients directions)],
2538 my $form = $self->form;
2540 my $s = "SELECT COUNT(*) FROM recipe WHERE title = ?";
2541 my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'});
2543 $self->add_errors(title => 'A recipe by this title already exists');
2547 $s = "INSERT INTO recipe (title, ingredients, directions, date_added)
2548 VALUES (?, ?, ?, ?)";
2549 $self->dbh->do($s, {}, $form->{'title'},
2550 $form->{'ingredients'},
2551 $form->{'directions'},
2554 $self->add_to_form(success => "Recipe added to the database");
2559 ###----------------------------------------------------------------###
2561 sub edit_skip { shift->form->{'id'} ? 0 : 1 }
2563 sub edit_hash_common {
2565 return {} if $self->ready_validate;
2567 my $sth = $self->dbh->prepare("SELECT * FROM recipe WHERE id = ?");
2568 $sth->execute($self->form->{'id'});
2569 my $hash = $sth->fetchrow_hashref;
2574 sub edit_hash_validation { shift->add_hash_validation(@_) }
2578 my $form = $self->form;
2580 my $s = "SELECT COUNT(*) FROM recipe WHERE title = ? AND id != ?";
2581 my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'}, $form->{'id'});
2583 $self->add_errors(title => 'A recipe by this title already exists');
2587 my $s = "UPDATE recipe SET title = ?, ingredients = ?, directions = ? WHERE id = ?";
2588 $self->dbh->do($s, {}, $form->{'title'},
2589 $form->{'ingredients'},
2590 $form->{'directions'},
2593 $self->add_to_form(success => "Recipe updated in the database");
2598 ###----------------------------------------------------------------###
2600 sub view_skip { shift->edit_skip(@_) }
2602 sub view_hash_common { shift->edit_hash_common(@_) }
2604 ###----------------------------------------------------------------###
2606 sub delete_skip { shift->edit_skip(@_) }
2608 sub delete_info_complete { 1 }
2610 sub delete_finalize {
2612 $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form->{'id'});
2614 $self->add_to_form(success => "Recipe deleted from the database");
2624 File: /var/www/templates/content/recipe/main.html
2625 ### --------------------------------------------
2628 <title>Recipe DB</title>
2632 [% IF success %]<span style="color:darkgreen"><h2>[% success %]</h2></span>[% END %]
2634 <table style="border:1px solid blue">
2635 <tr><th>#</th><th>Title</th><th>Date Added</th></tr>
2637 [% FOR row IN recipies %]
2639 <td>[% loop.count %].</td>
2640 <td><a href="[% script_name %]/view?id=[% row.id %]">[% row.title %]</a>
2641 (<a href="[% script_name %]/edit?id=[% row.id %]">Edit</a>)
2643 <td>[% row.date_added %]</td>
2647 <tr><td colspan=2 align=right><a href="[% script_name %]/add">Add new recipe</a></td></tr>
2653 File: /var/www/templates/content/recipe/edit.html
2654 ### --------------------------------------------
2657 <title>[% step == 'add' ? "Add" : "Edit" %] Recipe</title>
2659 <h1>[% step == 'add' ? "Add" : "Edit" %] Recipe</h1>
2661 <form method=post name=[% form_name %]>
2662 <input type=hidden name=step>
2666 [% IF step != 'add' ~%]
2668 <td><b>Id:</b></td><td>[% id %]</td></tr>
2669 <input type=hidden name=id>
2672 <td><b>Date Added:</b></td><td>[% date_added %]</td></tr>
2677 <td valign=top><b>Title:</b></td>
2678 <td><input type=text name=title>
2679 <span style='color:red' id=title_error>[% title_error %]</span></td>
2682 <td valign=top><b>Ingredients:</b></td>
2683 <td><textarea name=ingredients rows=10 cols=40 wrap=physical></textarea>
2684 <span style='color:red' id=ingredients_error>[% ingredients_error %]</span></td>
2687 <td valign=top><b>Directions:</b></td>
2688 <td><textarea name=directions rows=10 cols=40 wrap=virtual></textarea>
2689 <span style='color:red' id=directions_error>[% directions_error %]</span></td>
2692 <td colspan=2 align=right>
2693 <input type=submit value="[% step == 'add' ? 'Add' : 'Update' %]"></td>
2698 (<a href="[% script_name %]">Main Menu</a>)
2699 [% IF step != 'add' ~%]
2700 (<a href="[% script_name %]/delete?id=[% id %]">Delete this recipe</a>)
2708 File: /var/www/templates/content/recipe/view.html
2709 ### --------------------------------------------
2712 <title>[% title %] - Recipe DB</title>
2714 <h1>[% title %]</h1>
2715 <h3>Date Added: [% date_added %]</h3>
2717 <h2>Ingredients</h2>
2724 (<a href="[% script_name %]">Main Menu</a>)
2725 (<a href="[% script_name %]/edit?id=[% id %]">Edit this recipe</a>)
2729 ### --------------------------------------------
2733 The dbh method returns an SQLite dbh handle and auto creates the
2734 schema. You will normally want to use MySQL or Oracle, or Postgres
2735 and you will want your schema to NOT be auto-created.
2737 This sample uses hand rolled SQL. Class::DBI or a similar module
2738 might make this example shorter. However, more complex cases that
2739 need to involve two or three or four tables would probably be better
2740 off using the hand crafted SQL.
2742 This sample uses SQL. You could write the application to use whatever
2743 storage you want - or even to do nothing with the submitted data.
2745 We had to write our own HTML (Catalyst and Ruby on Rails do this for
2746 you). For most development work - the HTML should be in a static
2747 location so that it can be worked on by designers. It is nice that
2748 the other frameworks give you stub html - but that is all it is. It
2749 is worth about as much as copying and pasting the above examples. All
2750 worthwhile HTML will go through a non-automated design/finalization
2753 The add step used the same template as the edit step. We did
2754 this using the add_name_step hook which returned "edit". The template
2755 contains IF conditions to show different information if we were in
2756 add mode or edit mode.
2758 We reused code, validation, and templates. Code and data reuse is a
2761 The edit_hash_common returns an empty hashref if the form was ready to
2762 validate. When hash_common is called and the form is ready to
2763 validate, that means the form failed validation and is now printing
2764 out the page. To let us fall back and use the "sticky" form fields
2765 that were just submitted, we need to not provide values in the
2768 We use hash_common. Values from hash_common are used for both
2769 template swapping and filling. We could have used hash_swap and
2770 hash_fill independently.
2772 The hook main_info_complete is hard coded to 0. This basically says
2773 that we will never try and validate or finalize the main step - which
2774 is most often the case.
2776 =head1 SEPARATING STEPS INTO SEPARATE FILES
2778 It may be useful sometimes to separate some or all of the steps of an
2779 application into separate files. This is the way that CGI::Prototype
2780 works. This is useful in cases were some steps and their hooks are
2781 overly large - or are seldom used.
2783 The following modifications can be made to the previous "recipe db"
2784 example that would move the "delete" step into its own file. Similar
2785 actions can be taken to break other steps into their own file as well.
2788 ### File: /var/www/lib/Recipe.pm
2789 ### Same as before but add the following line:
2790 ### --------------------------------------------
2792 sub allow_morph { 1 }
2795 ### File: /var/www/lib/Recipe/Delete.pm
2796 ### Remove the delete_* subs from lib/Recipe.pm
2797 ### --------------------------------------------
2798 package Recipe::Delete;
2801 use base qw(Recipe);
2803 sub skip { shift->edit_skip(@_) }
2805 sub info_complete { 1 }
2809 $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form->{'id'});
2811 $self->add_to_form(success => "Recipe deleted from the database");
2818 The hooks that are called (skip, info_complete, and finalize) do not
2819 have to be prefixed with the step name because they are now in their
2820 own individual package space. However, they could still be named
2821 delete_skip, delete_info_complete, and delete_finalize and the
2822 run_hook method will find them (this would allow several steps with
2823 the same "morph_package" to still be stored in the same external
2826 The method allow_morph is passed the step that we are attempting to
2827 morph to. If allow_morph returns true every time, then it will try
2828 and require the extra packages every time that step is ran. You could
2829 limit the morphing process to run only on certain steps by using code
2830 similar to the following:
2832 sub allow_morph { return {delete => 1} }
2837 my ($self, $step) = @_;
2838 return ($step eq 'delete') ? 1 : 0;
2841 The CGI::Ex::App temporarily blesses the object into the
2842 "morph_package" for the duration of the step and re-blesses it into the
2843 original package upon exit. See the morph method and allow_morph for more
2846 =head1 RUNNING UNDER MOD_PERL
2848 The previous samples are essentially suitable for running under flat CGI,
2849 Fast CGI, or mod_perl Registry or mod_perl PerlRun type environments. It
2850 is very easy to move the previous example to be a true mod_perl handler.
2852 To convert the previous recipe example, simply add the following:
2854 ### File: /var/www/lib/Recipe.pm
2855 ### Same as before but add the following lines:
2856 ### --------------------------------------------
2864 ### File: apache2.conf - or whatever your apache conf file is.
2865 ### --------------------------------------------
2867 SetHandler perl-script
2873 Both the /cgi-bin/recipe version and the /recipe version can co-exist.
2874 One of them will be a normal cgi and the other will correctly use
2875 mod_perl hooks for headers.
2877 Setting the location to /recipe means that the $ENV{SCRIPT_NAME} will
2878 also be set to /recipe. This means that name_module method will
2879 resolve to "recipe". If a different URI location is desired such as
2880 "/my_cool_recipe" but the program is to use the same template content
2881 (in the /var/www/templates/content/recipe directory), then we would
2882 need to explicitly set the "name_module" parameter. It could be done
2883 in either of the following ways:
2885 ### File: /var/www/lib/Recipe.pm
2886 ### Same as before but add the following line:
2887 ### --------------------------------------------
2889 sub name_module { 'recipe' }
2895 $self->{'name_module'} = 'recipe';
2898 In most use cases it isn't necessary to set name_module, but it also
2899 doesn't hurt and in all cases it is more descriptive to anybody who is
2900 going to maintain the code later.
2902 =head1 ADDING AUTHENTICATION TO THE ENTIRE APPLICATION
2904 Having authentication is sometimes a good thing. To force
2905 the entire application to be authenticated (require a valid username
2906 and password before doing anything) you could do the following.
2908 ### File: /var/www/lib/Recipe.pm
2909 ### Same as before but add
2910 ### --------------------------------------------
2912 sub get_pass_by_user {
2915 my $pass = $self->lookup_and_cache_the_pass($user);
2920 ### File: /var/www/cgi-bin/recipe (depending upon Apache configuration)
2921 ### Change the line with ->navigate; to
2922 ### --------------------------------------------
2924 Recipe->navigate_authenticated;
2928 ### File: /var/www/lib/Recipe.pm
2929 ### Same as before but add
2930 ### --------------------------------------------
2932 sub require_auth { 1 }
2936 ### File: /var/www/lib/Recipe.pm
2937 ### Same as before but add
2938 ### --------------------------------------------
2940 sub init { shift->require_auth(1) }
2942 See the require_auth, get_valid_auth, and auth_args methods for more information.
2943 Also see the L<CGI::Ex::Auth> perldoc.
2945 =head1 ADDING AUTHENTICATION TO INDIVIDUAL STEPS
2947 Sometimes you may only want to have certain steps require
2948 authentication. For example, in the previous recipe example we
2949 might want to let the main and view steps be accessible to anybody,
2950 but require authentication for the add, edit, and delete steps.
2952 To do this, we would do the following to the original example (the
2953 navigation must start with ->navigate. Starting with ->navigate_authenticated
2954 will cause all steps to require validation):
2956 ### File: /var/www/lib/Recipe.pm
2957 ### Same as before but add
2958 ### --------------------------------------------
2960 sub get_pass_by_user {
2963 my $pass = $self->lookup_and_cache_the_pass($user);
2967 sub require_auth { {add => 1, edit => 1, delete => 1} }
2969 That's it. The add, edit, and delete steps will now require authentication.
2970 See the require_auth, get_valid_auth, and auth_args methods for more information.
2971 Also see the L<CGI::Ex::Auth> perldoc.
2975 The following corporation and individuals contributed in some part to
2976 the original versions.
2978 Bizhosting.com - giving a problem that fit basic design patterns.
2980 Earl Cahill - pushing the idea of more generic frameworks.
2982 Adam Erickson - design feedback, bugfixing, feature suggestions.
2984 James Lance - design feedback, bugfixing, feature suggestions.
2988 Paul Seamons <paul at seamons dot com>
2992 This module may be distributed under the same terms as Perl itself.