1Maypole::Manual::View(3U)ser Contributed Perl DocumentatiMoanypole::Manual::View(3)
2
3
4

NAME

6       Maypole::Manual::View - Maypole View Classes
7

DESCRIPTION

9       In a large application, you will almost certainly want to customize the
10       layout and design of the output pages. This task may even be the
11       purview of a separate team of HTML designers rather than the program‐
12       mers. Since a typical programmer will try to avoid touching HTML as
13       much as possible and a typical designer will try to avoid touching Perl
14       code, programmers have evolved a system of templating to separate the
15       concerns of programming and designing.
16
17       One of the core concepts in Maypole is the view class, and this is
18       responsible for routing the data produced in the model class into the
19       templates produced by the designers. Of course, there are a great many
20       possible templating systems and styles, and so there can be a great
21       many possible Maypole view classes. Each view class will take the data
22       from the controller, locate a template to be processed, and hand the
23       whole lot to its preferred templating module, which will then do the
24       hard work of filling in the template and coming up with the output.
25
26       You can choose whatever Maypole view class you want, but the default
27       view class is Maypole::View::TT, and it feeds its data and templates to
28       a module called the Template Toolkit.
29
30       The Template Toolkit
31
32       The Template Toolkit, written by Andy Wardley, is a very powerful and
33       generic templating system. It provides its own little formatting lan‐
34       guage which supports loops, conditionals, hash and array dereferences
35       and method calls, macro processing and a plug-in system to connect it
36       to external Perl modules.  Its homepage is "http://www.template-tool
37       kit.org/".  There are several good introductions to the Template Tool‐
38       kit available: you should have one installed as Template::Tuto‐
39       rial::Datafile; there's one at
40       <http://www.perl.com/pub/a/2003/07/15/nocode.html>, and of course
41       there's the "Badger Book" - The Perl Template Toolkit, by Andy et al.
42       "http://www.oreilly.com/catalog/perltt/index.html"
43
44       We'll present a brief introduction here by deconstructing some of the
45       templates used by Maypole applications. For more deconstruction, see
46       Standard Templates and Actions, which is an entire chapter dealing with
47       the factory supplied templates.
48
49       Here's a template that could be called for the front page of the exam‐
50       ple beer database application, "custom/frontpage".
51
52           [% INCLUDE header %]
53
54           <h2> The beer database </h2>
55
56           <TABLE BORDER="0" ALIGN="center" WIDTH="70%">
57           [% FOR table = config.display_tables %]
58           <TR>
59           <TD>
60           <A HREF="[%table%]/list">List by [%table %]</A>
61           </TD>
62           </TR>
63           [% END %]
64           </TABLE>
65
66       The first thing to note about this is that everything outside of the
67       Template Toolkit tags ("[%" and "%]") is output verbatim. That is,
68       somewhere in the output you're guaranteed to see
69
70           <h2> The beer database </h2>
71
72           <TABLE BORDER="0" ALIGN="center" WIDTH="70%">
73
74       Inside the tags, magic happens. The first piece of magic is the "[%
75       INCLUDE header %]" directive. This goes away and finds a file called
76       header - don't worry about how it finds that yet, we'll come to that
77       later on - and processes the file's contents as though they were right
78       there in the template. Our header file happens not to contain any "[%
79       %]" tags, but if it did, they would be processed in the same way as the
80       ones in frontpage.
81
82       The next piece of magic is this line:
83
84           [% FOR table = config.display_tables %]
85
86       We're seeing a lot of things here at once. "config" is where we should
87       start looking. This is a template variable, which is what templates are
88       all about - templating means getting data from somewhere outside and
89       presenting it to the user in a useful way, and "config" is a prime
90       example of data that we want to use. It's actually an object containing
91       configuration parameters for this Maypole application, and one of the
92       methods is "display_tables", which returns a list of the database
93       tables that we're supposed to show. In the application, we probably
94       said something like
95
96           BeerDB->config->display_tables([qw[beer brewery pub style]]);
97
98       This stores the four values - "beer", "brewery", "pub" and "style" - in
99       an array, which is placed in the config object using the accessor/muta‐
100       tor method "display_tables". Now we're getting them back again. Note
101       that we're not going to show the handpump table.
102
103       The Template Toolkit's dot operator is a sort of do-the-right-thing
104       operator; we can say "array.0" to get the first element of an array,
105       "hash.key" to look up the "key" key in a hash, and "object.method" to
106       call "method" on an object. So, for instance, if we said "config.dis‐
107       play_tables.2", we'd look up the "display_tables" method in the config‐
108       uration object and get our array back, then look up the 3rd element and
109       get "pub".  Thing is, you don't have to care whether "display_tables"
110       is an object or a hash. You can pretend it's a hash if you want. The
111       syntax is the same, and Template Toolkit knows the right thing to do.
112
113       The "FOR" loop will repeat the code four times, setting our new vari‐
114       able "table" to the appropriate array element. This code:
115
116           [% FOR table = config.display_tables %]
117               Hello [% table %]!
118           [% END %]
119
120       will produce something like
121
122           Hello beer!
123           Hello brewery!
124           Hello pub!
125           Hello style!
126
127       In our case, though, we're printing out a table element linking to each
128       database table in turn.
129
130       Here's a slightly more complicated example, adapted from factory/pager.
131       This template is responsible for printing the little page menu at the
132       bottom of a listing if there are more rows in the listing than we want
133       on a single page.
134
135           [% PROCESS macros %]
136           <P ALIGN="center">Pages:
137           [%
138                FOREACH num = [pager.first_page .. pager.last_page];
139                     IF num == pager.current_page;
140                       "["; num; "] ";
141                     ELSE;
142                       SET args = "?page=" _ num;
143                       SET label = "[" _ num _ "]";
144                       link(classmetadata.table, "list", args, label);
145                     END;
146                END;
147           %]
148           </P>
149
150       Maypole will be providing a whole bunch of variables to this template,
151       and we'll look at them all in a moment, but the only ones we need to
152       care about are "pager" and "classmetadata".
153
154       We start by loading in a bunch of macros. Macros are Template Toolkit's
155       functions - you can provide them some parameters and they'll run a lit‐
156       tle sub-template based on them. The "macros" file contains some handy
157       macros that I've found useful for constructing Maypole templates;
158       again, these will be covered in full detail in Standard Templates and
159       Actions.
160
161       We're going to be displaying something like this:
162
163           Pages: [1] [2] [3] [4]
164
165       with most of those numbers being a link to the appropriate page. This
166       mean we're going to have to have a list of numbers, and the "FOREACH"
167       loop provides this: ("FOREACH" and "FOR" are identical, just like in
168       Perl.)
169
170                FOREACH num = [pager.first_page .. pager.last_page];
171
172       Here we're manually constructing an array of numbers, using the range
173       operator ("..") to fill in all the numbers from the "first_page" (1) to
174       the "last_page" (4). The same dot operator is used to ask the "pager"
175       object what its "first_page" and "last_page" are.
176
177       Now we're going to be executing this loop four times, once each for
178       "num" being set to 1, 2, 3, and 4. At some point, we'll come across the
179       page that we're actually on right now:
180
181             IF num == pager.current_page;
182
183       and in that case, we don't want to produce a link to it. We just want
184       to output it as text, surrounded by square brackets:
185
186                       "["; num; "] ";
187
188       We're using string literals to output the brackets. We don't have to do
189       that. We could say it this way:
190
191           [% ...
192             IF num == pager.current_page;
193           %]
194               [ [% num %] ]
195           [% ELSE %]
196              ...
197           [% END %]
198
199       But you know, I quite like it my way.
200
201       Now if the number we're printing isn't the number of the current page,
202       we want to make a link. Here's how we do it:
203
204           SET args = "?page=" _ num;
205           SET label = "[" _ num _ "]";
206           link(classmetadata.table, "list", args, label);
207
208       "SET" declares a new variable of our own. If there was anything called
209       "args" before, there isn't now. It's going to be the result of our
210       statement ""?page=" _ num". "_" is the concatenation operator, and
211       glues "?page=" onto the front of our number. So if we want to link to
212       page 4, then the "args" variable will contain "?page=4". Similarly, the
213       "label" variable will be "[4]".
214
215       Now we call a macro, "link" with these two variables and the value of
216       "classmetadata.table". This macro takes four arguments, "table",
217       "action", "args" and "label", and constructs a link of the form
218
219           <A HREF="[% base %]/[% table %]/[% action %][% args %]">
220           [% label %]
221           </A>
222
223       In our case, it'll be filled in like so:
224
225           <A HREF="[% base %]/[% classmetadata.table %]/list?page=4">
226           [ 4 ]
227           </A>
228
229       Where "classmetadata.table" will actually be the name of the current
230       table, and "base" will be replaced by the appropriate URL for this
231       application.
232
233       Locating Templates
234
235       Another feature of "Maypole::View::TT" which may not be present in
236       alternate view class implementations - although they are strongly
237       encouraged to provide it - is the way that templates are located.
238       (Remember, I did say I'd tell you about that later.) Template Toolkit
239       allows whatever uses it to provide a path for template files to be
240       located in. "Maypole::View::TT" feeds it up to three possible directo‐
241       ries to look things up in, and it will try to find a template in each
242       of these in turn.
243
244       When you configure a Maypole application, you can tell it the base
245       directory of your templates like so:
246
247           BeerDB->config->template_root("/var/www/beerdb/templates");
248
249       If you don't do this, most Maypole front-ends will use the current
250       directory, which may be what you want anyway. Off this directory, May‐
251       pole will look for a set of subdirectories.
252
253       For instance, I said we were in the middle of processing the front page
254       and looking up a template file called header. Maypole will first look
255       for this file in the custom subdirectory. (say, /var/www/beerdb/tem‐
256       plates/custom) If it doesn't find one, then it looks in the factory
257       subdirectory. If it doesn't find one there, then it gives up and dies
258       with an error. But that's your fault, since you've called for a tem‐
259       plate which doesn't exist. Don't do that.
260
261       This behaviour means that you can provide your own site-specific tem‐
262       plates, but if you don't do so, then you get to use a generic one pro‐
263       vided by Maypole. Maypole's "factory setting" templates are written in
264       such a way as to try and do the right thing no matter what your appli‐
265       cation does. They are occasionally successful at this.
266
267       Now the front page was a pretty simple example, since Maypole only
268       looks up two directories. In most cases, it checks an additional direc‐
269       tory, and this directory depends entirely on what Maypole is doing.
270
271       If you're writing an e-commerce application, for example, you may well
272       have a table which represents the product catalogue and all the prod‐
273       ucts you can buy. Let's call this the "product" table. You'll also have
274       a data source which is specific to the user which contains all the
275       products that they're buying on this particular visit to the site. In
276       time-honoured tradition, we'll call this the "basket" table.
277
278       Now it ought to be reasonably apparent that you don't want the basket
279       to be displayed in exactly the same way as the product catalogue. The
280       templates for "product/list" and "basket/list" need to be different.
281       This is where the third directory comes in. The other directory, which
282       Maypole checks very first of all, is specific to the table that you're
283       viewing. So if you go to "http://your.shop.com/basket/list", Maypole
284       will look in the basket directory first for a file called list, and
285       second in the custom directory for a site-wide list template, and then
286       fall-back to the factory directory for a generic list template. It
287       should be obvious that you probably want to provide all of basket/list,
288       basket/view, product/list, product/view and any other combination of
289       classes and actions that you can think of.
290
291       What Maypole provides to a template
292
293       "Maypole::View::TT" provides quite a variety of template variables to
294       the template. As these are the building blocks of your pages, it's
295       worth looking at precisely what variables are available.
296
297       objects
298
299       The most important variable is called "objects", and is a list of all
300       the objects that this page is going to deal with. For instance, if the
301       URL is "http://localhost/beerdb/beer/view/23", then in the template
302       /beer/view, "objects" will contain the "BeerDB::Beer" object for the
303       23rd item in the database, while for the /brewery/list template, the
304       view will fill "objects" with all the breweries; or at least, all the
305       breweries on the current page.
306
307       breweries!
308
309       This variable is so important that to help design templates with it,
310       "Maypole::View::TT" provides a helpful alias to it depending on con‐
311       text. For instance, if you're writing your own /brewery/list template,
312       the data in "objects" is also available in a template variable called
313       "breweries". If you're working on /brewery/view, though, it's available
314       in "brewery", since there's only one brewery to be displayed.
315
316       base
317
318       Additionally, you can get the base URL for the application from the
319       "base" template variable; this allows you to construct links, as we saw
320       earlier:
321
322           <A HREF="[% base %]/brewery/edit/[% brewery.id %]">Edit this brewery</A>
323
324       config
325
326       You can also get at the rest of the configuration for the site with the
327       "config" variable as we saw above.
328
329       request
330
331       The entire request object is made available in "request", should you
332       really need to poke at it. (I've only found this useful when working
333       with authentication modules which stash a current user object in
334       "request.user".)
335
336       classmetadata
337
338       To allow the construction of the "generic" templates which live in fac‐
339       tory, Maypole also passes in a hash called "classmetadata", which con‐
340       tains all sorts of useful information about the class under examina‐
341       tion:
342
343       "table"
344          This is the name of the table that is represented by the class.
345
346       "name"
347          This is the Perl's idea of the class; you don't need this unless
348          you're doing really tricky things.
349
350       "moniker"
351          This is a more human-readable version of the table name, that can be
352          used for display. "brewery" for example.
353
354       "plural"
355          The same, but a correctly-formed plural. For instance, "breweries".
356
357       "columns"
358          The list of columns for display; see the hard way section in the
359          Beer Database chapter.
360
361       "list_columns"
362          As for "columns", but these are the columns to be displayed on a
363          list page.
364
365       "colnames"
366          This is a hash mapping the database's name for a column to a more
367          human-readable name. Again, see "Customizing Generic CRUD Applica‐
368          tions".
369
370       "cgi"
371          This is a slightly trickier one. It is a hash mapping column names
372          to a "HTML::Element" suitable for entering data into a new instance
373          of that class. That is, for the "beer" table, "classmeta‐
374          data.cgi.style" should be a "HTML::Element" object containing a
375          drop-down list of beer styles.
376
377       "related_accessors"
378          This is a list of accessors which can be called on an object to get
379          lists of other things that this object "has". For instance, on a
380          brewery, it would return "beers", since calling "brewery.beers"
381          would give you a list of beers produced by the brewery. Note that
382          this only caters for accessors defining one-to-many relationships,
383          not the ordinary one-to-one relationships, such as "style".
384
385       Additional variables and overrides
386
387       You can pass additional data to templates by creating new variables.
388       You'd typically do this in your view class.  Just add the name of your
389       template variable as a key to the "template_args" hash in the request
390       object, and supply its value:
391
392         $r->template_args->{your_variable_name} = 'some_value';
393
394       You can also override the value of any of the standard variables by
395       giving their name as the key.
396
397       Accessing other classes
398
399       When building a frontpage, login or other template that isn't directly
400       linked to a particular table, (and therefore it's class,) that you wish
401       to use, you can access the classes directly.
402
403       When using "Maypole::View::TT" you are reccomended to use Richard
404       Clamp's incredibly useful Template::Plugin::Class -- see the and Tem‐
405       plate::Plugin::Class and "Maypole::View::TT" documentation for details.
406
407       Mason and MasonX views also allow you to pull in arbitary classes, see
408       the relevent Mason and Plugin/View documentation for details.
409
410       If you are using HTML::Template you are out of luck on this front due
411       to philosophy and architecture this templating system cannot call code,
412       and only reads the data provided when the template is processed.
413
414       Other view classes
415
416       Please note that these template variables, "config", "classmetadata",
417       "objects" and its user-friendly alias, as well as the rest of them are
418       a function of one particular view class, the default "May‐
419       pole::View::TT" class. Other view classes may need to present an
420       entirely different set of template variables, since the default ones
421       might not make sense. The templates may look wildly different in other
422       view class implementations. But that's OK, because you couldn't neces‐
423       sarily use the same templates with a different templating system any‐
424       way.
425
426       For instance, in really dumb templating languages which can't handle
427       dereferencing hashes or arrays - no wait, that's most of them - passing
428       in a hash reference like "classmetadata" won't help you since you can't
429       get at any of its elements. So you'll need to take a look at the docu‐
430       mentation for the appropriate view class to see what template variables
431       it provides.
432
433       So if, for some perverse reason, the Template Toolkit just isn't good
434       enough for you, then you can set your own view class while configuring
435       your application:
436
437          package BeerDB;
438          use base Maypole::Application;
439          ...
440          BeerDB->setup("dbi:SQLite:t/beerdb.db");
441          BeerDB->config->uri_base(http://localhost/beerdb/");
442          BeerDB->config->rows_per_page(10);
443          BeerDB->config->view("Maypole::View::Mason");
444
445       Where do these alternate view classes come from? Gentle reader, they
446       come from you.
447
448       Building your own view class
449
450       You should probably skip this section for the first few readings of
451       this manual. It's only intended for people extending Maypole.
452
453       Imagine you've found a brand new templating system that's much better
454       than the Template Toolkit. I know I'm stretching your imagination a bit
455       here, but try. You'd like to use it with Maypole, which means writing
456       your own view class. How is it done?
457
458       We'll demonstrate by implementing a view class for HTML::Mason,
459       although no value judgement is implied. "HTML::Mason" is a templating
460       system which embeds pure Perl code inside its magic tags. The good side
461       of this is that it can get into hash references and objects, and so
462       providing "classmetadata", "config" and the Maypole request object will
463       work out just fine. The down side is that "HTML::Mason" is used to run‐
464       ning more or less standalone, and having all the template variables it
465       wants already at its disposal through CGI parameters and the like, so
466       we have to fiddle a bit to get these variables into our template.
467
468       The key to building view classes is Maypole::View::Base. This is the
469       base class that you're going to inherit from and, to be honest, it does
470       pretty much everything you need. It provides a method called "vars"
471       which returns a hash of all the template variables described above, so
472       it would be good to feed those into "HTML::Mason". It also provides a
473       "paths" method which turns returns the full filesystem path of the
474       three possible template paths as shown above. Again, it would be good
475       to use this as our component paths if we can. It also has some methods
476       we can override if we want to, but they're not massively important, so
477       you can see Maypole::View::Base for more about them.
478
479       The module will do the right thing for us if we agree to provide a
480       method called "template". This is responsible for taking the Maypole
481       request object $r (of which more later) and putting the appropriate
482       output either into "$r->output" or "$r->error", depending, of course,
483       whether things are OK or whether we got an error.
484
485       Thankfully, "HTML::Mason" makes things really easy for us. We can use
486       multiple template roots, so we can use the "paths" method; we can pass
487       in a hash full of interesting data structures, so we can use the "vars"
488       method too. In fact, we have to do very little to make "May‐
489       pole::View::Mason" work. Which is somewhat annoying, because it makes a
490       boring example. But it means I can leave the fun ones to you!
491
492       The doing-the-templating, in Mason and in any templating system,
493       depends on three things: the paths that we're going to use to find our
494       templates, the template name that we've been asked to fill out, and the
495       set of variables that are going to be fed to the template. We'll assem‐
496       ble these for reference:
497
498           sub template {
499               my ($self, $r) = @_;
500               my @paths = $self->paths($r);
501               my $template = $r->template;
502               my %vars = $self->args($r);
503
504       We'll also declare somewhere to temporarily store the output:
505
506               my $output;
507
508       Now comes the part where we have to actually do something templating-
509       language specific, so we open up our copy of "Embedding Perl in HTML
510       with Mason" and find the bit where it talks about running Mason stand‐
511       alone. We find that the first thing we need to do is create a
512       "HTML::Mason::Interp" object which knows about the component roots.
513       There's a slight subtlety in that the component roots have to be speci‐
514       fied as an array of arrays, with each array being a two-element list of
515       label and path, like so:
516
517           comproot => [
518               [ class   => "/var/www/beerdb/templates/brewery" ],
519               [ custom  => "/var/www/beerdb/templates/custom" ],
520               [ factory => "/var/www/beerdb/templates/factory" ],
521           ]
522
523       We also find that we can set the output method here to capture Mason's
524       output into a scalar, and also that we can tell Mason to generate sen‐
525       sible error messages itself, which saves us from having to worry about
526       catching errors. At the end of all this, we come up with a constructor
527       for our "HTML::Mason::Interp" object which looks like this:
528
529           my $label = "path0";
530           my $mason = HTML::Mason::Interp->new(
531               comproot => [ map { [ $label++ => $_ ] } @paths ],
532               output_method => \$output,
533               error_mode => "output"
534           );
535
536       The next thing we need to do is run the template with the appropriate
537       template variables. This turns out to be really easy:
538
539           $mason->exec($template, %vars);
540
541       Now we've got the data in $output, we can put it into the request
542       object, and return a true value to indicate that we processed every‐
543       thing OK. (If there was an error, then Mason will have produced some
544       suitable output, so we can pretend that everything's OK anyway.)
545
546           $r->output($output);
547           return 1;
548
549       And that's all we need to do. Barely twenty lines of code for the fin‐
550       ished product. Wasn't that easy? Don't you feel inspired to write May‐
551       pole view classes for your favourite templating language? Well, don't
552       let me stop you!  Patches are always welcome!
553
554       Links
555
556       Contents, Next Standard Templates and Actions, Previous Maypole Model
557       Classes,
558
559
560
561perl v5.8.8                       2005-11-23          Maypole::Manual::View(3)
Impressum