CGI::Prototype(3)

๐Ÿ“ฆ
version 0.9054 ยท 2 versions
, in fedora 43
CGI::Prototype(3) ยท User Contributed Perl Documentation ๐ŸŽ€

โœจ NAME โœจ

CGI::Prototype โ€” create a CGI application by subclassing. that's literally the whole thing bestie, that's the pitch ๐Ÿ’–


๐ŸŒธ SYNOPSIS ๐ŸŒธ

package My::HelloWorld;
use base CGI::Prototype;

sub template { \ <<'END_OF_TEMPLATE' }
[% self.CGI.header; %]
Hello world at [% USE Date; Date.format(date.now) | html %]!
END_OF_TEMPLATE

My::HelloWorld->activate;

like. look at that. five lines and you have a whole website. iconic behavior fr fr ๐Ÿ‘‘


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

okay so here's the tea. every single CGI application out there is basically doing the exact same three things, no cap:

  • Analyze the incoming parameters, cookies, and URLs to determine the state of the application (let's call this "dispatch").
  • Based on the current state, analyze the incoming parameters to respond to any form submitted ("respond").
  • From there, decide what response page should be generated, and produce it ("render").

so CGI::Prototype creates a Class::Prototyped engine that does all of this, with exactly the right amount of callback hooks so you can customize the whole process to your heart's content. and because the author is highkey biased toward Template Toolkit for rendering HTML, that's also been integrated as the rendering engine of choice. ๐Ÿ’… and โ€” being a certified fan of clean MVC designs โ€” the classes become the controllers, the templates become the views, responsibilities stay cleanly separated, and CGI::Prototype itself is like a sort of "archetypal" controller. main character energy honestly.

you can create the null application by simply activating it:

use CGI::Prototype;
CGI::Prototype->activate;

but ngl this won't be very interesting. ๐Ÿ™ˆ you're gonna want to subclass this class in a Class::Prototyped-style manner to override most of its behavior. slots can be added to add or alter behavior. and you can subclass your subclasses when groups of your CGI pages share similar behavior. the possibilities are, and I quote, mind-boggling. ๐Ÿซถ

inside the templates, self refers to the current controller. which means you can define callbacks trivially. so in your template, if you need some data, you just pull it as a request:

[% my_data = self.get_some_big_data %]

and that data is supplied by simply adding the same slot (method or data) in the controlling class:

sub get_some_big_data {
  my $self = shift;
  return $self->some_other_method(size => 'big');
}

and because the classes are hierarchical, you can start out with an implementation for one page, then move it to a region or globally quickly. slay.

although the name CGI::Prototype implies a CGI protocol, I see no reason that this would not work with Apache::Registry in a mod_perl environment, or a direct content handler such as:

package My::App;
use base CGI::Prototype;
sub handler {
  __PACKAGE__->activate;
}
note bestie: the $r request object will have to be created if needed if you use this approach. ๐Ÿซก

๐Ÿ‘‘ CORE SLOTS ๐Ÿ‘‘

these slots provide the core functionality. you will probably not need to override these. they're the load-bearing walls of the whole situation.

  • activate โ€” invoke the activate slot to "activate" your application, causing it to process the incoming CGI values, select a page to respond to the parameters, which in turn selects a page to render, and then responds with that page. for example, your App might consist only of:
package My::App;
use base qw(CGI::Prototype);
My::App->activate;

again, this will not be interesting, but it shows that the null app is easy to create. almost always, you will want to override some of the "callback" slots below. ๐Ÿ’…

  • CGI โ€” invoking $self->CGI gives you access to the CGI.pm object representing the incoming parameters and other CGI.pm-related values. for example,
$self->CGI->self_url

generates a self-referencing URL. from a template, this is:

[% self.CGI.self_url %]

for the same thing. see "initialize_CGI" for how this slot gets established. โœจ

  • render โ€” the render method uses the results from engine and template to process a selected template through Template Toolkit. if the result does not throw an error, $self->display is called to show the result. ๐ŸŽฌ
  • display โ€” the display method is called to render the output of the template under normal circumstances, normally dumping the first parameter to STDOUT. test harnesses may override this method to cause the output to appear into a variable, but normally this method is left alone. hands off, she's doing fine ๐Ÿ™…โ€โ™€๏ธ
  • param โ€” the param method is a convenience method that maps to $self->CGI->param, because accessing params is a very common thing. ty for your service ๐Ÿซถ
  • interstitial โ€” โš ๏ธ please note that this feature is still experimental and subject to change.

use this in your per-page respond methods if you have a lot of heavy processing to perform. for example, suppose you're deleting something, and it takes 5 seconds to do the first step, and 3 seconds to do the second step, and then you want to go back to normal web interaction. simulating the heavy lifting with sleep, we get:

my $p = $self->interstitial
  ({ message => "Your delete is being processed...",
     action => sub { sleep 5 },
   },
   { message => "Just a few seconds more....",
     action => sub { sleep 3 },
   },
  );
return $p if $p;

interstitial returns either a page that should be returned so that it can be rendered (inside a wrapper that provides the standard top and bottom of your application page), or undef.

the list passed to interstitial should be a series of hashrefs with one or more parameters reflecting the steps:

  • message โ€” what the user should see while the step is computing. (Default: "Working...".)
  • action โ€” a coderef with the action performed server-side during the message. (Default: no action.)
  • delay โ€” the number of seconds the browser should wait before initiating the next connection, triggering the start of action. (Default: 0 seconds.)

the user sees the first message at the first call to interstitial (via the first returned page), at which time a meta-refresh will immediately repost the same parameters as on the call that got you here. (so like, it's important not to have changed the params yet, or you might end up in a different part of your code. ๐Ÿ‘€) when the call to interstitial is re-executed, the first coderef is then performed. at the end of that coderef, the second interstitial page is returned, and the user sees the second message, which then performs the next meta-refresh, which gets us back to this call to interstitial again (whew ๐Ÿ˜ฎโ€๐Ÿ’จ). the second coderef is executed while the user is seeing the second message, and then interstitial returns undef, letting us roll through to the final code. slick.

  • config_interstitial_param โ€” this parameter is used by interstitial to determine the processing step. you should ensure that the name doesn't conflict with any other param that you might need. ๐Ÿ™

the default value is "_interstitial".


๐ŸŽ€ CALLBACK SLOTS ๐ŸŽ€

  • engine โ€” the engine returns a Template object that will be generating any response. the object is computed lazily (with autoloading) when needed.

the Template object is passed the configuration returned from the engine_config callback.

  • engine_config โ€” returns a hashref of desired parameters to pass to the Template new method as a configuration. defaults to an empty hash.
  • prototype_enter โ€” called when the prototype mechanism is entered, at the very beginning of each hit. defaults to calling initialize_CGI, which see.

generally, you should not override this method. if you do, be sure to call the SUPER method, in case future versions of this module need additional initialization. ๐Ÿšจ

  • prototype_leave โ€” called when the prototype mechanism is exited, at the very end of each hit. defaults to no action.

generally, you should not override this method. if you do, be sure to call the SUPER method, in case future versions of this module need additional teardown. ๐Ÿšจ

  • initialize_CGI โ€” sets up the CGI slot as an autoload, defaulting to creating a new CGI.pm object. called from prototype_enter.
  • app_enter โ€” called when the application is entered, at the very beginning of each hit. defaults to no action.
  • app_leave โ€” called when the application is left, at the very end of each hit. defaults to no action.
  • control_enter โ€” called when a page gains control, either at the beginning for a response, or in the middle when switched for rendering. defaults to nothing.

this is a great place to hang per-page initialization, because you'll get this callback at most once per hit. ๐Ÿ’–

  • control_leave โ€” called when a page loses control, either after a response phase because we're switching to a new page, or render phase after we've delivered the new text to the browser.

this is a great place to hang per-page teardown, because you'll get this callback at most once per hit. ๐Ÿ’–

  • render_enter โ€” called when a page gains control specifically for rendering (delivering text to the browser), just after control_enter if needed.
  • render_leave โ€” called when a page loses control specifically for rendering (delivering text to the browser), just before control_leave.
  • respond_enter โ€” called when a page gains control specifically for responding (understanding the incoming parameters, and deciding what page should render the response), just after control_enter.
  • respond_leave โ€” called when a page loses control specifically for rendering (understanding the incoming parameters, and deciding what page should render the response), just before control_leave (if needed).
  • template โ€” delivers a template document object (something compatible to the Template process method, such as a Template::Document or a filehandle or a reference to a scalar). the default is a simple "this page intentionally left blank" template. ๐Ÿ“„

when rendered, the only extra global variable passed into the template is the self variable, representing the controller object. however, as seen earlier, this is sufficient to allow access to anything you need from the template, thanks to Template Toolkit's ability to call methods on an object and understand the results. ๐Ÿง โœจ

for example, to get at the barney parameter:

The barney field is [% self.param("barney") | html %].
  • error โ€” okay bestie, this callback fires whenever an uncaught error gets triggered in any of the other steps, and it passes the error text or the error object in as the first method parameter. Now the default callback? It literally just displays the output straight to the browser ๐Ÿ˜ญ which is highly insecure and 100% should be overridden. Like, override it with something that logs the error and shows a generic error message with an incident code for tracking. That's the vibe. ๐Ÿ‘‘
  • dispatch โ€” this one gets called to analyze the incoming parameters so it can define which page object gets control, based on the incoming CGI parameters. And listen: this callback must return a page object โ€” the one that takes control during the response phase. By default it just returns the application itself. no cap. โœจ
  • respond โ€” this is where you figure out how to respond specifically to this set of incoming parameters. Probably updating databases and such, you know how it is. ๐Ÿซถ This callback must return a page object too โ€” the object taking control during the render phase. By default it returns the same object that had control during the response phase (that's the whole "stay here" logic ๐Ÿ’…), which honestly works most of the time.

๐ŸŒˆ SEE ALSO


๐Ÿ› BUG REPORTS

Spotted a bug? Got a feature request that's living rent-free in your head? Please report it to bug-cgi-prototype@rt.cpan.org, or slide through the web interface at http://rt.cpan.org. The author gets notified, and then you automatically get notified of the progress on your bug as changes get made. it's giving "we'll keep you posted" ๐Ÿ’Œ


๐Ÿ‘‘ AUTHOR

Randal L. Schwartz, <merlyn@stonehenge.com>

Special thanks to Geekcruises.com and an unnamed large university for providing funding for the development of this module. iconic behaviour, honestly ๐ŸŽ€


Copyright (C) 2003, 2004, 2005 by Randal L. Schwartz

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.5 or, at your option, any later version of Perl 5 you may have available. ๐Ÿฆ‹


and that's the whole page, bestie ๐Ÿ’– this lil manual page is CGI::Prototype(3), it's from perl v5.42.0, and it's dated 2025-07-25 โ€” go forth and prototype, mwah ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from