Main Content

Perl Dancer - from installation to your first real application

Archive - Originally posted on "The Horse's Mouth" - 2013-05-24 17:31:35 - Graham Ellis

Previous article - Perl Dancer - Installation and first test. Summary of that article - What is Dancer / How do I install it / Installing requires CPAN modules / Creating an application / testing that it worked.

The application in the first article provides you with no more that a welcome page to tell you that you have installed Perl Dancer and it's functioning. This article is the second step - telling you how to add your own content within the framework.

Adding in your own route and code

Modify bin/app.pl to read:

  #!/usr/bin/env perl
  use Dancer;
  use MyWeb::App;
  
  sub hometown {
    return "What a great place to live!";
    }
  
  get '/town/melksham.html' => \&hometown;
  
  dance;


And that (yes, it really is that easy to start!) is your first application.

The call to the get function is your route, telling the web server to send any requests for the /town/melksham.html URL to the hometown function.

sub hometown is your rudimentary controller, simply returning a string of HTML that's to be rendered.

And it looks like this:



A little more routing - a whole family of pages to a single controller

If you want to add a whole pattern of pages - support multiple URLs through a single controller - you can do so by adding a named parameter to your router:

  get '/town/:where.html' => \&awaytown;

and picking up that parameter through the params method in the controller method - for example

  sub awaytown {
    return params->{where} . " is quite nice but ... ".
      "have you thought of moving to ".
      "<a href=/town/melksham.html>Melksham</a>?";
    }



 

 


Adding in a template

You'll note that I've been referring to our hometown and awaytown methods as controllers, and yet they've contained the look and feel elements (the view). Let's move that view out into a separate template, so that we can start to separate out the business logic from the look and feel.

  sub hometown {
    my $saying = "<h4>What a great place to live!&t;/h4>".
      "Come along to <a href=http://melksh.am/hotel>".
      "Well House Manor</a> and we'll welcome you";
    my %fillings = (dynamics => $saying, pagename => "melksham");
    template ('township.tt',\%fillings);
    }


Alas, I then find I've got another dependency issue:

  munchkin:bin grahamellis$ ./app.pl
  Can't locate Template.pm in @INC (@INC contains: /Users/grahamellis/Dancer-1.3113/MyWeb-App/lib /Library/Perl/5.12/darwin-thread-multi-2level /Library/Perl/5.12 /Network/Library/Perl/5.12/darwin-thread-multi-2level /Network/Library/Perl/5.12 /Library/Perl/Updates/5.12.3/darwin-thread-multi-2level /Library/Perl/Updates/5.12.3 /System/Library/Perl/5.12/darwin-thread-multi-2level /System/Library/Perl/5.12 /System/Library/Perl/Extras/5.12/darwin-thread-multi-2level /System/Library/Perl/Extras/5.12 .) at ./app.pl line 3.
BEGIN failed--compilation aborted at ./app.pl line 3.


Oops - let's load that from the CPAN:

  munchkin:bin grahamellis$ sudo perl -MCPAN -e shell
  Password:
  cpan[1]> install Template


and run again... viewing the pages gives:



The problem being that we haven't provided the template yet! Let's do so, in file township.tt in the views directory:

  <h1>This is a Township!</h1>
  This line of text is within a template that I've applied right through
  the town application, and filled in with various dynamic fields. You called
  this up under the name "<% pagename %>". All sorts of standard stuff would
  be going here, which would have dynamics merged into it. Here comes the main
  dynamic block:<hr />
  <% dynamics %>
  <hr />
  As well as all the headers, you'll want small print such as<br />
  Copyright <a href=http://www.wellho.net>Well House Consultants</a><br />
  and a link to the top of this app <a href=/town/>[here]</a> or
  search page <a href=/town/search.html>[here]</a>.


You'll note that our template is standard .html, with additional markers between <% and %> markers saying where data is to be inserted. And it'll now work:


 

 


Providing your wrapper template and style

The application's starting to look rather good, even though we've written minimal code. But there's still the Dance logo and copyright statement which we won't want on our production sites - how do I replace / update them?

Dancer applications have an overall, surrounding layout around each and every page - it's a sort of super-template. Upon installation, the file that's used for the outer layout is called layouts/main.tt - and you can either change it or (better) provide a replacement, and point Dancer to that replacement via the config.yml file. In that file, change
  layout: "main"
to
  layout: "wellhouseframe"

And in the wellhouseframe.tt provide something like this:

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <meta http-equiv="Content-type" content="text/html; charset=<% settings.charset %>" />
  <title>This is my page <% pagename %></title>
  <link rel="stylesheet" href="<% request.uri_base %>/css/townstyle.css" />
  </head>
  <body>
  <% content %>
  <div id="footer">
  Written by Graham Ellis of Well House Consultants / Perl Dancer teaching example
  </div>
  </body>
  </html>


Note the use of <% content %> to instruct the templating system where to insert the inner template.

I have modified a copy of main.tt rather than entered this from scratch. Similarly, take the style sheet file that the original installation came with, modify it and save it under the name that's in the layout. Changes I made here included adding in margins all around, changing the background colour, and removing the watermark image. Results...


 


Adding in a form

The final example also included:
* a form in a new template
* collecting information from that form
* redirection to a result page if the form is [correctly] completed, or returning the original form again if not
* Using either the POST or the GET methods to submit that form.



Complete source code for this final example:
./bin/app - the controllers and routes
township.tt - the main template pafe
askuser.tt - the form template
wellhouseframe.tt - the surrounding layout template
config.yml - the configuration for Dancer
townstyle.css - the amended style sheet