CGI::Prototype (NPW 2006)

16,925 views
16,752 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
16,925
On SlideShare
0
From Embeds
0
Number of Embeds
26
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

CGI::Prototype (NPW 2006)

  1. 1. Managing Complexity with CGI::Prototype brian d foy, brian@stonehenge.com Stonehenge Consulting Ser vices Nordic Perl Workshop • June 16, 2006
  2. 2. Web application flow Start up Receive input Process input Return output Clean up Shut down
  3. 3. Looks simple, right?
  4. 4. Is the request valid? Should I process the transaction? Do I have all the necessary input? Is this part of a multi-step process? Which output do I give?
  5. 5. Language agnostic
  6. 6. Current fad is Model-View-Controller (MVC)
  7. 7. MVC Architecture Model -> data store -> database View -> data display -> web page Controller -> user interaction -> form widgets
  8. 8. Choose your poison Mason CGI::Application Maypole, Catalyst, Catalyst++ CGI::Prototype
  9. 9. Using CGI::Prototype Model -> DBI, Class::DBI, XML View -> Template Toolkit, XSLT -> HTML Controller -> HTML form widgets
  10. 10. Application state Each state is a namespace Each state has a Template file Change state at any time by changing namespace
  11. 11. Application flow Inherit from CGI::Prototype Single URL WebApp->activate; The rest is in packages and templates CGI::Prototype handles the flow
  12. 12. sub activate { my $self = shift; eval { $self->app_enter; my $this_page = $self->dispatch; $this_page->control_enter; $this_page->respond_enter; my $next_page = $this_page->respond; $this_page->respond_leave; if ($this_page ne $next_page) { $this_page->control_leave; $next_page->control_enter; } $next_page->render_enter; $next_page->render; $next_page->render_leave; $next_page->control_leave; $self->app_leave; }; $self->error($@) if $@; }
  13. 13. package TPR::Dashboard::FindByName; use base qw(TPR::Dashboard); my $users = []; sub respond { my $self = shift; my $q = $self->CGI; my $name = $q->param('subscriber_name'); $users = $self->db->get_subscriber_by_name( $name ) || []; my $count = @$users; if( @$users == 1 ){ $q->param( 'subscriber_id', $users->[0]->pk ); quot;TPR::CGI::ShowSubscriberquot;; } elsif( @$users == 0 ) { quot;TPR::CGI::StartPagequot;; } else { __PACKAGE__; } } sub users { $users }
  14. 14. Flexibility Change action by changing namespace CGI::Prototype object handles the input and data (Class::Prototyped) in $self Choose template with template() Template has access to self.foo
  15. 15. Handling Errors Respond with Error namespace Rest of transaction does Error stuff Still has access to all data CGI::Prototype has safe mode (no 500s, hopefully)
  16. 16. Multiple Responses Decide which template to use as late as possible No search results -> show search form One search result -> show details Many search results -> show list Database error -> show error page
  17. 17. [% self.CGI.header %] <!DOCTYPE ...> <html> <head> <title>[% self.title %]</title> <link rel=quot;stylesheetquot; type=quot;text/cssquot; href=quot;... quot;/> </head> <body> <div id=quot;headerquot; class=quot;menubarquot;> ... </div> <div id=quot;contentquot; class=quot;middlequot;> <!-- BEGIN Content [% template %] --> [% PROCESS $template %] <!-- END Content [% template %] --> </div> <div id=quot;footerquot;> </div> </body></html>
  18. 18. Add accessors... sub action { quot;add_subscriberquot; } sub title { quot;Add a subscriberquot; } my $db = TPR::Subscribers::Database::SQLite->new( $file ); sub db { $db } sub subscriber { $_[0]->db->get_subscriber_by_pk( $_[1] ); }
  19. 19. ...use them in Template <title>[% self.title %]</title> [% self.CGI.start_form( Method => quot;GETquot;, Action => self.CGI.url, ) %] [% self.CGI.hidden( Name => 'action', Value => self.action, Override => 1, ) -%]
  20. 20. The View just views Accessors are just accessors Do not change the state Change the state in the Controller All views then get the feature
  21. 21. Change behavior __PACKAGE__->reflect->addSlots( [qw(engine FIELD autoload)] => sub { my $self = shift; require Template; Template->new( { PROCESS => [ $self->config_wrapper ], INCLUDE_PATH => quot;/web/cgi-bin/local-templatesquot;, } ); } ); sub config_wrapper { 'Wrapper.tt' } sub template { (my $package = ref $_[0] || $_[0]) =~ s/.*:://; my $file = quot;$package.ttquot;; -e quot;/web/cgi-bin/local-templates/$filequot; ? $file : quot;I could not find $package.ttquot;; }
  22. 22. CGI::Prototype::Hidden is even easier
  23. 23. References Introduction to CGI::Prototype http://www.ourmedia.org/node/1644 Introduction to Class::Prototyped http://www.ourmedia.org/node/1728 Various articles on stonehenge.com

×