Prev fix should have moved the "=over 4" vs. removing it to balance out "=back"
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / MoreCatalystBasics.pod
3533daff 1=head1 NAME
3Catalyst::Manual::Tutorial::MoreCatalystBasics - Catalyst Tutorial - Part 3: More Catalyst Application Development Basics
6=head1 OVERVIEW
8This is B<Part 3 of 10> for the Catalyst tutorial.
10L<Tutorial Overview|Catalyst::Manual::Tutorial>
12=over 4
14=item 1
18=item 2
20L<Catalyst Basics|Catalyst::Manual::Tutorial::CatalystBasics>
22=item 3
24B<More Catalyst Basics>
26=item 4
28L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
30=item 5
34=item 6
38=item 7
42=item 8
46=item 9
48L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
50=item 10
1390ef0e 59This part of the tutorial builds on the work done in Part 2 to explore
60some features that are more typical of "real world" web applications.
61From this part of the tutorial onward, we will be building a simple
62book database application. Although the application will be too
63limited to be of use to anyone, it should provide a basic environment
64where we can explore a variety of features used in virtually all web
3533daff 65applications.
67You can checkout the source code for this example from the catalyst
68subversion repository as per the instructions in
1390ef0e 69L<Catalyst::Manual::Tutorial::Intro|Catalyst::Manual::Tutorial::Intro>.
3533daff 70
1390ef0e 74The remainder of the tutorial will build an application called C<MyApp>.
75First use the Catalyst C<> script to initialize the framework
76for the C<MyApp> application (make sure you aren't still inside the
77directory of the C<Hello> application from the previous part of the
3533daff 78tutorial):
80 $ MyApp
81 created "MyApp"
82 created "MyApp/script"
83 created "MyApp/lib"
84 created "MyApp/root"
85 ...
86 created "MyApp/script/"
87 $ cd MyApp
1390ef0e 89This creates a similar skeletal structure to what we saw in Part 2 of
90the tutorial, except with C<MyApp> and C<myapp> substituted for
3533daff 91C<Hello> and C<hello>.
96One of the greatest benefits of Catalyst is that it has such a large
1390ef0e 97library of plugins and base classes available. Plugins are used to
98seamlessly integrate existing Perl modules into the overall Catalyst
99framework. In general, they do this by adding additional methods to the
100C<context> object (generally written as C<$c>) that Catalyst passes to
101every component throughout the framework.
3533daff 102
103By default, Catalyst enables three plugins/flags:
105=over 4
1390ef0e 107=item *
3533daff 108
109C<-Debug> Flag
111Enables the Catalyst debug output you saw when we started the
112C<script/> development server earlier. You can remove
79a529cc 113this item when you place your application into production.
3533daff 114
1390ef0e 115As you may have noticed, C<-Debug> is not a plugin, but a I<flag>.
116Although most of the items specified on the C<__PACKAGE__-E<gt>setup>
117line of your application class will be plugins, Catalyst supports a
118limited number of flag options (of these, C<-Debug> is the most
119common). See the documentation for C<> to get details on
120other flags (currently C<-Engine>, C<-Home>, and C<-Log>).
3533daff 121
122If you prefer, you can use the C<$c-E<gt>debug> method to enable debug
125B<TIP>: Depending on your needs, it can be helpful to permanently
126remove C<-Debug> from C<lib/> and then use the C<-d> option
127to C<script/> to re-enable it just for the development
1390ef0e 128server. We will not be using that approach in the tutorial, but feel
3533daff 129free to make use of it in your own projects.
131=item *
135C<ConfigLoader> provides an automatic way to load configurable
c010ae0d 136parameters for your application from a central
137L<Config::General|Config::General> file (versus having the values
138hard-coded inside your Perl modules). Config::General uses syntax
139very similar to Apache configuration files. We will see how to use
140this feature of Catalyst during the authentication and authorization
141sections (Part 5 and Part 6).
3533daff 142
1390ef0e 143B<IMPORTANT NOTE:> If you are using a version of
144L<Catalyst::Devel|Catalyst::Devel> prior to version 1.06, you need to
145be aware that Catalyst changed from a default format of YAML to the
146more straightforward C<Config::General> format. This tutorial use the
147newer C<myapp.conf> configuration file for C<Config::General> instead
148of C<myapp.yml> for YAML. However, Catalyst has long supported both
149formats and Catalyst will automatically use either C<myapp.conf> or
150C<myapp.yml> (or any other format supported by
056394af 151L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader> and
1390ef0e 152L<Config::Any|Config::Any>). If you are using a versions of
153Catalyst::Devel prior to 1.06, you can convert to the newer format by
8a0214b4 154simply creating the C<myapp.conf> file manually and deleting
1390ef0e 155C<myapp.yml>. The default contents of C<myapp.conf> should only
156consist of one line: C<name MyApp>.
15e1d0b2 157
1390ef0e 158B<TIP>: This script can be useful for converting between configuration
15e1d0b2 159formats:
1390ef0e 161 perl -Ilib -e 'use MyApp; use Config::General;
15e1d0b2 162 Config::General->new->save_file("myapp.conf", MyApp->config);'
d0496197 164B<NOTE:> The default C<myapp.conf> should look like:
166 name MyApp
15e1d0b2 167
3533daff 168=item *
172C<Static::Simple> provides an easy method of serving static content such
173as images and CSS files under the development server.
94d8da41 177For our application, we want to add one new plugin into the mix. To
1390ef0e 178do this, edit C<lib/> (this file is generally referred to as
179your I<application class>) and delete the line with:
3533daff 180
1390ef0e 181 __PACKAGE__->setup(qw/-Debug ConfigLoader Static::Simple/);
3533daff 182
1390ef0e 183Then replace it with:
b411df01 184
1390ef0e 185 __PACKAGE__->setup(qw/
186 -Debug
187 ConfigLoader
188 Static::Simple
190 StackTrace
191 /);
94d8da41 193B<Note:> Recent versions of C<Catalyst::Devel> have used a variety of
194techniques to load these plugins/flags. If you are following along in
195Ubuntu 8.10, you should have C<Catalyst::Devel> v1.07 and see the
196default code shown above. If you are using v1.08, you should see the
197following by default:
199 use Catalyst qw/-Debug
200 ConfigLoader
201 Static::Simple/;
202 ...
203 __PACKAGE__->setup();
205Don't let these variations confuse you -- they all accomplish the same
1390ef0e 208This tells Catalyst to start using one new plugin,
209L<Catalyst::Plugin::StackTrace|Catalyst::Plugin::StackTrace>, to add a
210stack trace to the standard Catalyst "debug screen" (the screen
211Catalyst sends to your browser when an error occurs). Be aware that
212L<StackTrace|Catalyst::Plugin::StackTrace> output appears in your
213browser, not in the console window from which you're running your
214application, which is where logging output usually goes.
3533daff 215
1390ef0e 216B<Notes:>
3533daff 217
218=over 4
1390ef0e 220=item *
222C<__PACKAGE__> is just a shorthand way of referencing the name of the
223package where it is used. Therefore, in C<>, C<__PACKAGE__>
224is equivalent to C<MyApp>.
3533daff 225
1390ef0e 226=item *
3533daff 227
1390ef0e 228You will want to disable L<StackTrace|Catalyst::Plugin::StackTrace>
229before you put your application into production, but it can be helpful
230during development.
3533daff 231
1390ef0e 232=item *
3533daff 233
1390ef0e 234When specifying plugins on the C<__PACKAGE__-E<gt>setup> line, you can
235omit C<Catalyst::Plugin::> from the name. Additionally, you can
236spread the plugin names across multiple lines as shown here, or place
237them all on one (or more) lines as with the default configuration.
cca5cd98 238
3533daff 239=back
3533daff 241
1390ef0e 244As discussed earlier, controllers are where you write methods that
245interact with user input. Typically, controller methods respond to
3533daff 246C<GET> and C<POST> messages from the user's web browser.
248Use the Catalyst C<create> script to add a controller for book-related
251 $ script/ controller Books
252 exists "/home/me/MyApp/script/../lib/MyApp/Controller"
253 exists "/home/me/MyApp/script/../t"
254 created "/home/me/MyApp/script/../lib/MyApp/Controller/"
255 created "/home/me/MyApp/script/../t/controller_Books.t"
1390ef0e 257Then edit C<lib/MyApp/Controller/> (as discussed in Part 2 of
258the Tutorial, Catalyst has a separate directory under C<lib/MyApp> for
259each of the three parts of MVC: C<Model>, C<View>, and C<Controller>)
260and add the following method to the controller:
3533daff 261
262 =head2 list
264 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
266 =cut
1390ef0e 267
3533daff 268 sub list : Local {
269 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
270 # 'Context' that's used to 'glue together' the various components
271 # that make up the application
272 my ($self, $c) = @_;
274 # Retrieve all of the book records as book model objects and store in the
275 # stash where they can be accessed by the TT template
1390ef0e 276 # $c->stash->{books} = [$c->model('DB::Books')->all];
277 # But, for now, use this code until we create the model later
278 $c->stash->{books} = '';
3533daff 280 # Set the TT template to use. You will almost always want to do this
281 # in your action methods (action methods respond to user input in
282 # your controllers).
283 $c->stash->{template} = 'books/list.tt2';
284 }
1390ef0e 286B<TIP>: See Appendix 1 for tips on removing the leading spaces when
287cutting and pasting example code from POD-based documents.
3533daff 288
1390ef0e 289Programmers experienced with object-oriented Perl should recognize
290C<$self> as a reference to the object where this method was called.
291On the other hand, C<$c> will be new to many Perl programmers who have
292not used Catalyst before (it's sometimes written as C<$context>). The
293Context object is automatically passed to all Catalyst components. It
294is used to pass information between components and provide access to
295Catalyst and plugin functionality.
3533daff 296
245b41d1 297Catalyst actions are regular Perl methods, but they make use of
298attributes (the "C<: Local>" next to the "C<sub list>" in the code
0416017e 299above) to provide additional information to the Catalyst dispatcher
300logic (note that the space between the colon and the attribute name is
245b41d1 301optional... you will see attributes written both ways). Most Catalyst
302Controllers use one of five action types:
0416017e 303
304=over 4
306=item *
245b41d1 308B<:Private> -- Use C<:Private> for methods that you want to make into
309an action, but you do not want Catalyst to directly expose the action
310to your users. Catalyst will not map C<:Private> methods to a URI.
311Use them for various sorts of "special" methods (the C<begin>,
312C<auto>, etc. discussed below) or for methods you want to be able to
313C<forward> or C<detach> to. (If the method is a plain old "helper
314method" that you don't want to be an action at all, then just define
315the method without any attribute -- you can call it in your code, but
316the Catalyst dispatcher will ignore it.)
0416017e 317
245b41d1 318There are five types of "special" build-in C<:Private> actions:
319C<begin>, C<end>, C<default>, C<index>, and C<auto>.
0416017e 320
26c9cad5 321=over 4
0416017e 323=item *
325With C<begin>, C<end>, C<default>, C<index> private actions, only the
326most specific action of each type will be called. For example, if you
327define a C<begin> action in your controller it will I<override> a
328C<begin> action in your application/root controller -- I<only> the
329action in your controller will be called.
331=item *
333Unlike the other actions where only a single method is called for each
334request, I<every> auto action along the chain of namespaces will be
335called. Each C<auto> action will be called I<from the application/root
336controller down through the most specific class>.
340=item *
245b41d1 342B<:Path> -- C<:Path> actions let you map a method to an explicit URI
343path. For example, "C<:Path('list')>" in
0416017e 344C<lib/MyApp/Controller/> would match on the URL
245b41d1 345C<http://localhost:3000/books/list> but "C<:Path('/list')>" would match
346on C<http://localhost:3000/list>. You can use C<:Args()> to specify
347how many arguments an action should except. See
348L<Catalyst::Manual::Intro/Action_types> for more information and a few
0416017e 349examples.
351=item *
245b41d1 353B<:Local> -- C<:Local> is merely a shorthand for
354"C<:Path('_name_of_method_')>". For example, these are equivalent:
355"C<sub create_book :Local {...}>" and
356"C<sub create_book :Path('create_book') {...}>".
358=item *
360B<:Global> -- C<:Global> is merely a shorthand for
361"C<:Path('/_name_of_method_')>". For example, these are equivalent:
362"C<sub create_book :Global {...}>" and
363"C<sub create_book :Path('/create_book') {...}>".
365=item *
367B<:Chained> -- Newer Catalyst applications tend to use the Chained
0416017e 368dispatch form of action types because of its power and flexibility.
369It allows a series of controller methods to automatically be dispatched
370to service a single user request. See
372and L<Catalyst::DispatchType::Chained|Catalyst::DispatchType::Chained>
373for more information on chained actions.
377You should refer to L<Catalyst::Manual::Intro/Action_types> for
378additional information and for coverage of some lesser-used action
245b41d1 379types not discussed here (C<Regex> and C<LocalRegex>).
3533daff 380
384As mentioned in Part 2 of the tutorial, views are where you render
1390ef0e 385output, typically for display in the user's web browser (but also
386possibly using other display output-generation systems). The code in
387C<lib/MyApp/View> selects the I<type> of view to use, with the actual
388rendering template found in the C<root> directory. As with virtually
389every aspect of Catalyst, options abound when it comes to the specific
390view technology you adopt inside your application. However, most
391Catalyst applications use the Template Toolkit, known as TT (for more
392information on TT, see L<>). Other
393somewhat popular view technologies include Mason
394(L<> and L<>) and
395L<HTML::Template> (L<>).
398=head2 Create a Catalyst View
3533daff 399
400When using TT for the Catalyst view, there are two main helper scripts:
402=over 4
404=item *
408=item *
de966eb4 414Both helpers are similar. C<TT> creates the C<lib/MyApp/View/>
3533daff 415file and leaves the creation of any hierarchical template organization
416entirely up to you. (It also creates a C<t/view_TT.t> file for testing;
de966eb4 417test cases will be discussed in Part 8.) C<TTSite>, on the other hand,
418creates a modular and hierarchical view layout with
1390ef0e 419separate Template Toolkit (TT) files for common header and footer
420information, configuration values, a CSS stylesheet, and more.
de966eb4 422While C<TTSite> was useful to bootstrap a project, its use is now
423deprecated and to be considered historical. For most Catalyst
424applications it adds redundant functionality and structure; many in the
425Catalyst community recommend that it's easier to learn both Catalyst and
426Template Toolkit if you use the more basic C<TT> approach.
427Consequently, this tutorial will use "plain old TT."
1390ef0e 428
429Enter the following command to enable the C<TT> style of view
3533daff 430rendering for this tutorial:
1390ef0e 432 $ script/ view TT TT
3533daff 433 exists "/home/me/MyApp/script/../lib/MyApp/View"
434 exists "/home/me/MyApp/script/../t"
1390ef0e 435 created "/home/me/MyApp/script/../lib/MyApp/View/"
436 created "/home/me/MyApp/script/../t/view_TT.t"
3533daff 437
1390ef0e 438This simply creates a view called C<TT> (the second 'TT' argument) in
439a file called C<> (the first 'TT' argument). It is now up to you
440to decide how you want to structure your view layout. For the
441tutorial, we will start with a very simple TT template to initially
442demonstrate the concepts, but quickly migrate to a more typical
443"wrapper page" type of configuration (where the "wrapper" controls the
444overall "look and feel" of your site from a single file or set of
3533daff 446
1390ef0e 447Edit C<lib/MyApp/View/> and you should see that the default
448contents contains something similar to the following:
3533daff 449
1390ef0e 450 __PACKAGE__->config(TEMPLATE_EXTENSION => '.tt');
3533daff 451
1390ef0e 452And update it to match:
454 __PACKAGE__->config(
455 # Change default TT extension
457 # Set the location for TT files
6abd3023 459 MyApp->path_to( 'root', 'src' ),
1390ef0e 460 ],
461 );
3533daff 462
1390ef0e 463B<NOTE:> Make sure to add a comma after '.tt2' outside the single
191dee29 466This changes the default extension for Template Toolkit from '.tt' to
1390ef0e 467'.tt2' and changes the base directory for your template files from
de966eb4 468C<root> to C<root/src>. These changes from the default are done mostly
469to facilitate the application we're developing in this tutorial; as with
470most things Perl, there's more than one way to do it...
1390ef0e 471
473=head2 Create a TT Template Page
3533daff 474
475First create a directory for book-related TT templates:
1390ef0e 477 $ mkdir -p root/src/books
3533daff 478
479Then create C<root/src/books/list.tt2> in your editor and enter:
481 [% # This is a TT comment. The '-' at the end "chomps" the newline. You won't -%]
482 [% # see this "chomping" in your browser because HTML ignores blank lines, but -%]
483 [% # it WILL eliminate a blank line if you view the HTML source. It's purely -%]
484 [%- # optional, but both the beginning and the ending TT tags support chomping. -%]
1390ef0e 486 [% # Provide a title -%]
3533daff 487 [% META title = 'Book List' -%]
489 <table>
490 <tr><th>Title</th><th>Rating</th><th>Author(s)</th></tr>
491 [% # Display each book in a table row %]
492 [% FOREACH book IN books -%]
493 <tr>
494 <td>[% book.title %]</td>
495 <td>[% book.rating %]</td>
496 </tr>
497 [% END -%]
498 </table>
500As indicated by the inline comments above, the C<META title> line uses
1390ef0e 501TT's META feature to provide a title to the "wrapper" that we will
502create later. Meanwhile, the C<FOREACH> loop iterates through each
503C<book> model object and prints the C<title> and C<rating> fields.
3533daff 504
505If you are new to TT, the C<[%> and C<%]> tags are used to delimit TT
506code. TT supports a wide variety of directives for "calling" other
507files, looping, conditional logic, etc. In general, TT simplifies the
508usual range of Perl operators down to the single dot (C<.>) operator.
509This applies to operations as diverse as method calls, hash lookups, and
510list index values (see
55beb65d 511L<>
3533daff 512for details and examples). In addition to the usual C<Template> module
513Pod documentation, you can access the TT manual at
55beb65d 514L<>.
3533daff 515
1390ef0e 516B<TIP:> While you can build all sorts of complex logic into your TT
517templates, you should in general keep the "code" part of your templates
518as simple as possible. If you need more complex logic, create helper
519methods in your model that abstract out a set of code into a single call
520from your TT template. (Note that the same is true of your controller
521logic as well -- complex sections of code in your controllers should
522often be pulled out and placed into your model objects.)
525=head2 Test Run The Application
527To test your work so far, first start the development server:
529 $ script/
531Then point your browser to L<http://localhost:3000> and you should
532still get the Catalyst welcome page. Next, change the URL in your
533browser to L<http://localhost:3000/books/list>. If you have
534everything working so far, you should see a web page that displays
535nothing other than our column headers for "Title", "Rating", and
536"Author(s)" -- we will not see any books until we get the database and
537model working below.
539If you run into problems getting your application to run correctly, it
540might be helpful to refer to some of the debugging techniques covered in
541the L<Debugging|Catalyst::Manual::Tutorial::Debugging> part of the
3533daff 543
547In this step, we make a text file with the required SQL commands to
1390ef0e 548create a database table and load some sample data. We will use SQLite,
549a popular database that is lightweight and easy to use. Open
550C<myapp01.sql> in your editor and enter:
3533daff 551
552 --
553 -- Create a very simple database to hold book and author information
554 --
555 CREATE TABLE books (
557 title TEXT ,
558 rating INTEGER
559 );
560 -- 'book_authors' is a many-to-many join table between books & authors
561 CREATE TABLE book_authors (
562 book_id INTEGER,
563 author_id INTEGER,
564 PRIMARY KEY (book_id, author_id)
565 );
566 CREATE TABLE authors (
568 first_name TEXT,
569 last_name TEXT
570 );
571 ---
572 --- Load some sample data
573 ---
574 INSERT INTO books VALUES (1, 'CCSP SNRS Exam Certification Guide', 5);
575 INSERT INTO books VALUES (2, 'TCP/IP Illustrated, Volume 1', 5);
576 INSERT INTO books VALUES (3, 'Internetworking with TCP/IP Vol.1', 4);
577 INSERT INTO books VALUES (4, 'Perl Cookbook', 5);
578 INSERT INTO books VALUES (5, 'Designing with Web Standards', 5);
579 INSERT INTO authors VALUES (1, 'Greg', 'Bastien');
580 INSERT INTO authors VALUES (2, 'Sara', 'Nasseh');
581 INSERT INTO authors VALUES (3, 'Christian', 'Degu');
582 INSERT INTO authors VALUES (4, 'Richard', 'Stevens');
583 INSERT INTO authors VALUES (5, 'Douglas', 'Comer');
584 INSERT INTO authors VALUES (6, 'Tom', 'Christiansen');
585 INSERT INTO authors VALUES (7, 'Nathan', 'Torkington');
586 INSERT INTO authors VALUES (8, 'Jeffrey', 'Zeldman');
587 INSERT INTO book_authors VALUES (1, 1);
588 INSERT INTO book_authors VALUES (1, 2);
589 INSERT INTO book_authors VALUES (1, 3);
590 INSERT INTO book_authors VALUES (2, 4);
591 INSERT INTO book_authors VALUES (3, 5);
592 INSERT INTO book_authors VALUES (4, 6);
593 INSERT INTO book_authors VALUES (4, 7);
594 INSERT INTO book_authors VALUES (5, 8);
3533daff 596Then use the following command to build a C<myapp.db> SQLite database:
598 $ sqlite3 myapp.db < myapp01.sql
600If you need to create the database more than once, you probably want to
601issue the C<rm myapp.db> command to delete the database before you use
1390ef0e 602the C<sqlite3 myapp.db E<lt> myapp01.sql> command.
3533daff 603
604Once the C<myapp.db> database file has been created and initialized, you
605can use the SQLite command line environment to do a quick dump of the
606database contents:
608 $ sqlite3 myapp.db
609 SQLite version 3.4.2
610 Enter ".help" for instructions
611 sqlite> select * from books;
612 1|CCSP SNRS Exam Certification Guide|5
613 2|TCP/IP Illustrated, Volume 1|5
614 3|Internetworking with TCP/IP Vol.1|4
615 4|Perl Cookbook|5
616 5|Designing with Web Standards|5
617 sqlite> .q
618 $
622 $ sqlite3 myapp.db "select * from books"
623 1|CCSP SNRS Exam Certification Guide|5
624 2|TCP/IP Illustrated, Volume 1|5
625 3|Internetworking with TCP/IP Vol.1|4
626 4|Perl Cookbook|5
627 5|Designing with Web Standards|5
629As with most other SQL tools, if you are using the full "interactive"
630environment you need to terminate your SQL commands with a ";" (it's not
631required if you do a single SQL statement on the command line). Use
632".q" to exit from SQLite from the SQLite interactive mode and return to
633your OS command prompt.
a6d800ac 635For using other databases, such as PostgreSQL or MySQL, see
636L<Appendix 2|Catalyst::Manual::Tutorial::Appendices>.
3533daff 637
191dee29 640Catalyst can be used with virtually any form of persistent datastore
641available via Perl. For example,
642L<Catalyst::Model::DBI|Catalyst::Model::DBI> can be used to easily
643access databases through the traditional Perl C<DBI> interface. However,
644most Catalyst applications use some form of ORM technology to
645automatically create and save model objects as they are used. Although
646L<Class::DBI|Class::DBI> has been a popular choice in the past, Matt
647Trout's L<DBIx::Class|DBIx::Class> (abbreviated as "DBIC") has rapidly
648emerged as the Perl-based ORM technology of choice. Most new Catalyst
649applications rely on DBIC, as will this tutorial.
3533daff 650
3533daff 651
1390ef0e 652=head2 Create a Dynamic DBIC Model
654Use the C<create=dynamic> model helper option to build a model that
3533daff 655dynamically reads your database structure every time the application
d0496197 658 $ script/ model DB DBIC::Schema MyApp::Schema create=dynamic dbi:SQLite:myapp.db
1390ef0e 659 exists "/home/me/MyApp/script/../lib/MyApp/Model"
660 exists "/home/me/MyApp/script/../t"
661 exists "/home/me/MyApp/script/../lib/MyApp"
662 created "/home/me/MyApp/script/../lib/MyApp/"
663 created "/home/me/MyApp/script/../lib/MyApp/Model/"
664 created "/home/me/MyApp/script/../t/model_DB.t"
3533daff 665
d0496197 667C<DB> is the name of the model class to be created by the helper in
1390ef0e 668C<lib/MyApp/Model>. C<DBIC::Schema> is the type of the model to
669create. C<MyApp::Schema> is the name of the DBIC schema file written
670to C<lib/MyApp/>. Because we specified C<create=dynamic> to
671the helper, it use
672L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> to
673dynamically load the schema information from the database every time
c93b5eaa 674the application starts. DBIC uses the schema to load other classes
675that represent the tables in your database (DBIC refers to these
676"table objects" as "result sources," see
677L<DBIx::Class::ResultSource|DBIx::Class::ResultSource>). And finally,
678C<dbi:SQLite:myapp.db> is the standard DBI connect string for use with
3533daff 680
d0496197 681B<NOTE:> Although the C<create=dynamic> option to the DBIC helper
19c49089 682makes for a nifty demonstration, is only really suitable for very
683small applications. After this demonstration, you should almost always
684use the C<create=static> option that we switch to below.
dc9a0503 685
191dee29 689Open C<lib/MyApp/Controller/> and un-comment the model code we
690left disabled earlier (un-comment the line containing
1390ef0e 691C<[$c-E<gt>model('DB::Books')-E<gt>all]> and delete the next 2 lines):
693 =head2 list
695 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
697 =cut
699 sub list : Local {
700 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
701 # 'Context' that's used to 'glue together' the various components
702 # that make up the application
703 my ($self, $c) = @_;
705 # Retrieve all of the book records as book model objects and store in the
706 # stash where they can be accessed by the TT template
707 $c->stash->{books} = [$c->model('DB::Books')->all];
709 # Set the TT template to use. You will almost always want to do this
710 # in your action methods (action methods respond to user input in
711 # your controllers).
712 $c->stash->{template} = 'books/list.tt2';
713 }
c93b5eaa 715B<TIP>: You may see the C<$c-E<gt>model('DB::Book')> un-commented
716above written as C<$c-E<gt>model('DB')-E<gt>resultset('Book')>. The
717two are equivalent. Either way, C<$c-E<gt>model> returns a
718L<DBIx::Class::ResultSet|DBIx::Class::ResultSet> which handles queries
719against the database and iterating over the set of results that are
722We are using the C<-E<gt>all> to fetch all of the books. DBIC
723supports a wide variety of more advanced operations to easily do
724things like filtering and sorting the results. For example, the
518f3851 725following could be used to sort the results by descending title:
c93b5eaa 726
727 $c->model('DB::Books')->search({}, {order_by => 'title DESC'});
729Some other examples are provided in
730L<DBIx::Class::Manual::Cookbook/Complex WHERE clauses>, with
731additional information found at L<DBIx::Class::ResultSet/search>,
734and L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema>.
1390ef0e 735
737=head2 Test Run The Application
3533daff 738
739First, let's enable an environment variable option that causes
740DBIx::Class to dump the SQL statements it's using to access the database
741(this option can provide extremely helpful troubleshooting information):
743 $ export DBIC_TRACE=1
745This assumes you are using BASH as your shell -- adjust accordingly if
746you are using a different shell (for example, under tcsh, use
747C<setenv DBIC_TRACE 1>).
d0496197 749B<NOTE:> You can also set this in your code using
3533daff 750C<$class-E<gt>storage-E<gt>debug(1);>. See
751L<DBIx::Class::Manual::Troubleshooting> for details (including options
752to log to file instead of displaying to the Catalyst development server
1390ef0e 755Then launch the Catalyst development server. The log output should
756display something like:
3533daff 757
758 $script/
759 [debug] Debug messages enabled
1390ef0e 760 [debug] Statistics enabled
3533daff 761 [debug] Loaded plugins:
762 .----------------------------------------------------------------------------.
1390ef0e 763 | Catalyst::Plugin::ConfigLoader 0.20 |
764 | Catalyst::Plugin::StackTrace 0.08 |
3533daff 765 | Catalyst::Plugin::Static::Simple 0.20 |
766 '----------------------------------------------------------------------------'
768 [debug] Loaded dispatcher "Catalyst::Dispatcher"
769 [debug] Loaded engine "Catalyst::Engine::HTTP"
770 [debug] Found home "/home/me/MyApp"
45d511e0 771 [debug] Loaded Config "/home/me/MyApp/myapp.conf"
3533daff 772 [debug] Loaded components:
773 .-----------------------------------------------------------------+----------.
774 | Class | Type |
775 +-----------------------------------------------------------------+----------+
776 | MyApp::Controller::Books | instance |
777 | MyApp::Controller::Root | instance |
d0496197 778 | MyApp::Model::DB | instance |
779 | MyApp::Model::DB::Authors | class |
780 | MyApp::Model::DB::BookAuthors | class |
781 | MyApp::Model::DB::Books | class |
3533daff 782 | MyApp::View::TT | instance |
783 '-----------------------------------------------------------------+----------'
785 [debug] Loaded Private actions:
786 .----------------------+--------------------------------------+--------------.
787 | Private | Class | Method |
788 +----------------------+--------------------------------------+--------------+
789 | /default | MyApp::Controller::Root | default |
790 | /end | MyApp::Controller::Root | end |
1390ef0e 791 | /index | MyApp::Controller::Root | index |
3533daff 792 | /books/index | MyApp::Controller::Books | index |
793 | /books/list | MyApp::Controller::Books | list |
794 '----------------------+--------------------------------------+--------------'
796 [debug] Loaded Path actions:
797 .-------------------------------------+--------------------------------------.
798 | Path | Private |
799 +-------------------------------------+--------------------------------------+
1390ef0e 800 | / | /default |
801 | / | /index |
802 | /books | /books/index |
3533daff 803 | /books/list | /books/list |
804 '-------------------------------------+--------------------------------------'
1390ef0e 806 [info] MyApp powered by Catalyst 5.7014
3533daff 807 You can connect to your server at http://localhost:3000
1390ef0e 809B<NOTE:> Be sure you run the C<script/> command from
810the 'base' directory of your application, not inside the C<script>
811directory itself or it will not be able to locate the C<myapp.db>
812database file. You can use a fully qualified or a relative path to
813locate the database file, but we did not specify that when we ran the
3533daff 814model helper earlier.
816Some things you should note in the output above:
818=over 4
1390ef0e 820=item *
3533daff 821
1390ef0e 822Catalyst::Model::DBIC::Schema dynamically created three model classes,
823one to represent each of the three tables in our database
d0496197 824(C<MyApp::Model::DB::Authors>, C<MyApp::Model::DB::BookAuthors>,
825and C<MyApp::Model::DB::Books>).
3533daff 826
1390ef0e 827=item *
3533daff 828
829The "list" action in our Books controller showed up with a path of
834Point your browser to L<http://localhost:3000> and you should still get
835the Catalyst welcome page.
837Next, to view the book list, change the URL in your browser to
838L<http://localhost:3000/books/list>. You should get a list of the five
1390ef0e 839books loaded by the C<myapp01.sql> script above without any formatting.
840The rating for each book should appear on each row, but the "Author(s)"
191dee29 841column will still be blank (we will fill that in later).
3533daff 842
843Also notice in the output of the C<script/> that DBIC
844used the following SQL to retrieve the data:
846 SELECT, me.title, me.rating FROM books me
848because we enabled DBIC_TRACE.
0c51850e 850You now have the beginnings of a simple but workable web application.
3533daff 851Continue on to future sections and we will develop the application
852more fully.
1390ef0e 855=head1 CREATE A WRAPPER FOR THE VIEW
857When using TT, you can (and should!) create a wrapper that will
858literally wrap content around each of your templates. This is
859certainly useful as you have one main source for changing things that
860will appear across your entire site/application instead of having to
861edit many individual files.
864=head2 Configure For The Wrapper
866In order to create a wrapper, you must first edit your TT view and
867tell it where to find your wrapper file. Your TT view is located in
870Edit C<lib/MyApp/View/> and change it to match the following:
872 __PACKAGE__->config(
873 # Change default TT extension
875 # Set the location for TT files
c2dfb562 877 MyApp->path_to( 'root', 'src' ),
1390ef0e 878 ],
879 # Set to 1 for detailed timer stats in your HTML as comments
880 TIMER => 0,
881 # This is your wrapper template located in the 'root/src'
882 WRAPPER => 'wrapper.tt2',
883 );
886=head2 Create the Wrapper Template File and Stylesheet
888Next you need to set up your wrapper template. Basically, you'll want
889to take the overall layout of your site and put it into this file.
890For the tutorial, open C<root/src/wrapper.tt2> and input the following:
892 <?xml version="1.0" encoding="UTF-8"?>
893 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
894 <html xmlns="" xml:lang="en" lang="en">
895 <head>
896 <title>[% template.title or "My Catalyst App!" %]</title>
897 <link rel="stylesheet" href="[% c.uri_for('/static/css/main.css') %]" />
898 </head>
900 <body>
901 <div id="outer">
902 <div id="header">
903 [%# Your logo could go here -%]
904 <img src="[% c.uri_for('/static/images/btn_88x31_powered.png') %]" />
905 [%# Insert the page title -%]
906 <h1>[% template.title or site.title %]</h1>
907 </div>
909 <div id="bodyblock">
910 <div id="menu">
911 Navigation:
912 <ul>
913 <li><a href="[% c.uri_for('/books/list') %]">Home</a></li>
914 <li><a href="[% c.uri_for('/') %]" title="Catalyst Welcome Page">Welcome</a></li>
915 <li><a href="" title="Contact Us">Contact Us</a></li>
916 </ul>
917 </div><!-- end menu -->
919 <div id="content">
920 [%# Status and error messages %]
921 <span class="message">[% status_msg %]</span>
922 <span class="error">[% error_msg %]</span>
923 [%# This is where TT will stick all of your template's contents. -%]
924 [% content %]
925 </div><!-- end content -->
926 </div><!-- end bodyblock -->
928 <div id="footer">Copyright (c) your name goes here</div>
c2dfb562 929 </div><!-- end outer -->
1390ef0e 930
931 </body>
932 </html>
934Notice the status and error message sections in the code above:
936 <span class="status">[% status_msg %]</span>
937 <span class="error">[% error_msg %]</span>
939If we set either message in the Catalyst stash (e.g.,
940C<$c-E<gt>stash-E<gt>{status_msg} = 'Request was successful!'>) it
941will be displayed whenever any view used by that request is rendered.
942The C<message> and C<error> CSS styles can be customized to suit your
943needs in the C<root/static/css/main.css> file we create below.
947=over 4
949=item *
951The Catalyst stash only lasts for a single HTTP request. If
952you need to retain information across requests you can use
953L<Catalyst::Plugin::Session|Catalyst::Plugin::Session> (we will use
954Catalyst sessions in the Authentication part of the tutorial).
956=item *
958Although it is beyond the scope of this tutorial, you may wish to use
959a JavaScript or AJAX tool such as jQuery (L<>) or
960Dojo (L<>).
965=head3 Create A Basic Stylesheet
967First create a central location for stylesheets under the static
970 $ mkdir root/static/css
972Then open the file C<root/static/css/main.css> (the file referenced in
973the stylesheet href link of our wrapper above) and add the following
976 #header {
977 text-align: center;
978 }
979 #header h1 {
980 margin: 0;
981 }
982 #header img {
983 float: right;
984 }
985 #footer {
986 text-align: center;
987 font-style: italic;
988 padding-top: 20px;
989 }
990 #menu {
991 font-weight: bold;
992 background-color: #ddd;
993 }
994 #menu ul {
995 list-style: none;
996 float: left;
997 margin: 0;
998 padding: 0 0 50% 5px;
999 font-weight: normal;
1000 background-color: #ddd;
1001 width: 100px;
1002 }
1003 #content {
1004 margin-left: 120px;
1005 }
1006 .message {
1007 color: #390;
1008 }
1009 .error {
1010 color: #f00;
1011 }
1013You may wish to check out a "CSS Framework" like Emastic
1014(L<>) as a way to quickly
1015provide lots of high-quality CSS functionality.
1018=head2 Test Run The Application
1020Restart the development server and hit "Reload" in your web browser
1021and you should now see a formatted version of our basic book list.
1022Although our wrapper and stylesheet are obviously very simple, you
1023should see how it allows us to control the overall look of an entire
1024website from two central files. To add new pages to the site, just
1025provide a template that fills in the C<content> section of our wrapper
1026template -- the wrapper will provide the overall feel of the page.
3533daff 1029=head1 A STATIC DATABASE MODEL WITH C<DBIx::Class>
1031=head2 Create Static DBIC Schema Files
1390ef0e 1033Unlike the previous DBIC section where we had C<create=dynamic>
1034automatically discover the structure of the database every time the
1035application started, here we will use static schema files for more
1036control. This is typical of most "real world" applications.
3533daff 1037
1390ef0e 1038One option would be to manually create a separate schema file for each
1039table in the database, however, lets use the same
1040L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> used
1041earlier with C<create=dynamic> to build the static files for us.
9ad715b3 1042First, lets remove the schema file created earlier:
3533daff 1043
1390ef0e 1044 $ rm lib/MyApp/
3533daff 1045
1046Now regenerate the schema using the C<create=static> option:
d0496197 1048 $ script/ model DB DBIC::Schema MyApp::Schema create=static dbi:SQLite:myapp.db
1049 exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model"
1050 exists "/home/kclark/dev/MyApp/script/../t"
1051 Dumping manual schema for MyApp::Schema to directory /home/kclark/dev/MyApp/script/../lib ...
3533daff 1052 Schema dump completed.
d0496197 1053 exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model/"
3533daff 1054
1390ef0e 1055We could have also deleted C<lib/MyApp/Model/>, but it would
3533daff 1056have regenerated the same file (note the C<exists> in the output above).
d0496197 1057If you take a look at C<lib/MyApp/Model/>, it simply contains
1058a reference to the actual schema file in C<lib/MyApp/>
3533daff 1059along with the database connect string.
1390ef0e 1061If you look in the C<lib/MyApp/> file, you will find that it
1062is no longer using
1063L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> as its base
1064class (L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> is
1065only being used by the helper to load the schema once and then create
1066the static files for us) and C<> only contains a call to the
c2dfb562 1067C<load_classes> method. You will also find that C<lib/MyApp>
1390ef0e 1068contains a C<Schema> subdirectory, with one file inside this directory
1069for each of the tables in our simple database (C<>,
1070C<>, and C<>). These three files were created
1071based on the information found by
1072L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> as the
1073helper ran.
1075The idea with all of the files created under C<lib/MyApp/Schema> by
1076the C<create=static> option is to only edit the files below the C<# DO
1077NOT MODIFY THIS OR ANYTHING ABOVE!> warning. If you place all of your
3533daff 1078changes below that point in the file, you can regenerate the
1390ef0e 1079automatically created information at the top of each file should your
1080database structure get updated.
3533daff 1081
1390ef0e 1082Also note the "flow" of the model information across the various files
1083and directories. Catalyst will initially load the model from
d0496197 1084C<lib/MyApp/Model/>. This file contains a reference to
1085C<lib/MyApp/>, so that file is loaded next. Finally,
1390ef0e 1086the call to C<load_classes> in C<> will load each of the
d0496197 1087table-specific "results source" files from the C<lib/MyApp/Schema>
1390ef0e 1088subdirectory. These three table-specific DBIC schema files will then be
1089used to create three table-specific Catalyst models every time the
3533daff 1090application starts (you can see these three model files listed in
1091the debug output generated when you launch the application).
1094=head2 Updating the Generated DBIC Schema Files
3533daff 1096Let's manually add some relationship information to the auto-generated
d0496197 1097schema files. First edit C<lib/MyApp/Schema/> and
1390ef0e 1098add the following text below the C<# You can replace this text...>
3533daff 1099comment:
1101 #
1102 # Set relationships:
1390ef0e 1103 #
3533daff 1104
1105 # has_many():
1106 # args:
1107 # 1) Name of relationship, DBIC will create accessor with this name
1108 # 2) Name of the model class referenced by this relationship
1109 # 3) Column name in *foreign* table
d0496197 1110 __PACKAGE__->has_many(book_authors => 'MyApp::Schema::BookAuthors', 'book_id');
3533daff 1111
1112 # many_to_many():
1113 # args:
1114 # 1) Name of relationship, DBIC will create accessor with this name
1390ef0e 1115 # 2) Name of has_many() relationship this many_to_many() is shortcut for
1116 # 3) Name of belongs_to() relationship in model class of has_many() above
3533daff 1117 # You must already have the has_many() defined to use a many_to_many().
1118 __PACKAGE__->many_to_many(authors => 'book_authors', 'author');
1121B<Note:> Be careful to put this code I<above> the C<1;> at the end of the
1122file. As with any Perl package, we need to end the last line with
1123a statement that evaluates to C<true>. This is customarily done with
1124C<1;> on a line by itself.
1390ef0e 1126This code defines both a C<has_many> and a C<many_to_many> relationship.
1127The C<many_to_many> relationship is optional, but it makes it easier to
1128map a book to its collection of authors. Without it, we would have to
1129"walk" though the C<book_authors> table as in
1131(we will see examples on how to use DBIC objects in your code soon,
1132but note that because C<$book-E<gt>book_authors> can return multiple
1133authors, we have to use C<first> to display a single author).
1134C<many_to_many> allows us to use the shorter
1136Note that you cannot define a C<many_to_many> relationship without
1137also having the C<has_many> relationship in place.
3533daff 1138
d0496197 1139Then edit C<lib/MyApp/Schema/> and add relationship
3533daff 1140information as follows (again, be careful to put in above the C<1;> but
1141below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment):
1143 #
1144 # Set relationships:
1145 #
1147 # has_many():
1148 # args:
1149 # 1) Name of relationship, DBIC will create accessor with this name
1150 # 2) Name of the model class referenced by this relationship
1151 # 3) Column name in *foreign* table
d0496197 1152 __PACKAGE__->has_many(book_author => 'MyApp::Schema::BookAuthors', 'author_id');
3533daff 1153
1154 # many_to_many():
1155 # args:
1156 # 1) Name of relationship, DBIC will create accessor with this name
1157 # 2) Name of has_many() relationship this many_to_many() is shortcut for
1390ef0e 1158 # 3) Name of belongs_to() relationship in model class of has_many() above
3533daff 1159 # You must already have the has_many() defined to use a many_to_many().
1160 __PACKAGE__->many_to_many(books => 'book_author', 'book');
1390ef0e 1162Finally, do the same for the "join table,"
d0496197 1163C<lib/MyApp/Schema/>:
3533daff 1164
1165 #
1166 # Set relationships:
1167 #
1169 # belongs_to():
1170 # args:
1171 # 1) Name of relationship, DBIC will create accessor with this name
1172 # 2) Name of the model class referenced by this relationship
1173 # 3) Column name in *this* table
d0496197 1174 __PACKAGE__->belongs_to(book => 'MyApp::Schema::Books', 'book_id');
3533daff 1175
1176 # belongs_to():
1177 # args:
1178 # 1) Name of relationship, DBIC will create accessor with this name
1179 # 2) Name of the model class referenced by this relationship
1180 # 3) Column name in *this* table
d0496197 1181 __PACKAGE__->belongs_to(author => 'MyApp::Schema::Authors', 'author_id');
3533daff 1182
1390ef0e 1184=head2 Run The Application
3533daff 1185
1186Run the Catalyst "demo server" script with the C<DBIC_TRACE> option
1187(it might still be enabled from earlier in the tutorial, but here
1188is an alternate way to specify the option just in case):
1190 $ DBIC_TRACE=1 script/
1390ef0e 1192Make sure that the application loads correctly and that you see the
1193three dynamically created model class (one for each of the
3533daff 1194table-specific schema classes we created).
c2dfb562 1196Then hit the URL L<http://localhost:3000/books/list> and be sure that
1197the book list is displayed via the relationships established above. You
1198can leave the development server running for the next step if you wish.
3533daff 1199
c2dfb562 1200B<Note:> You will not see the authors yet because the view does not yet
1201use the new relations. Read on to the next section where we update the
1202template to do that.
3533daff 1203
1207Let's add a new column to our book list page that takes advantage of
1208the relationship information we manually added to our schema files
1209in the previous section. Edit C<root/src/books/list.tt2> add add the
1210following code below the existing table cell that contains
1390ef0e 1211C<book.rating> (IOW, add a new table cell below the existing two
3533daff 1212C<td> cells):
1214 <td>
1215 [% # First initialize a TT variable to hold a list. Then use a TT FOREACH -%]
1216 [% # loop in 'side effect notation' to load just the last names of the -%]
a0c5188a 1217 [% # authors into the list. Note that the 'push' TT vmethod does not print -%]
3533daff 1218 [% # a value, so nothing will be printed here. But, if you have something -%]
1219 [% # in TT that does return a method and you don't want it printed, you -%]
1220 [% # can: 1) assign it to a bogus value, or 2) use the CALL keyword to -%]
1221 [% # call it and discard the return value. -%]
1222 [% tt_authors = [ ];
1223 tt_authors.push(author.last_name) FOREACH author = book.authors %]
1224 [% # Now use a TT 'virtual method' to display the author count in parens -%]
1225 [% # Note the use of the TT filter "| html" to escape dangerous characters -%]
1226 ([% tt_authors.size | html %])
1227 [% # Use another TT vmethod to join & print the names & comma separators -%]
1228 [% tt_authors.join(', ') | html %]
1229 </td>
1390ef0e 1231Then hit "Reload" in your browser (note that you don't need to reload
3533daff 1232the development server or use the C<-r> option when updating TT
1390ef0e 1233templates) and you should now see the number of authors each book has
1234along with a comma-separated list of the authors' last names. (If you
1235didn't leave the development server running from the previous step,
1236you will obviously need to start it before you can refresh your
1237browser window.)
1239If you are still running the development server with C<DBIC_TRACE>
1240enabled, you should also now see five more C<SELECT> statements in the
1241debug output (one for each book as the authors are being retrieved by
3533daff 1242DBIC).
c2dfb562 1244 SELECT, me.title, me.rating FROM books me:
1245 SELECT me.book_id, me.author_id FROM book_authors me WHERE ( me.book_id = ? ): '1'
1246 SELECT me.book_id, me.author_id FROM book_authors me WHERE ( me.book_id = ? ): '2'
1247 SELECT me.book_id, me.author_id FROM book_authors me WHERE ( me.book_id = ? ): '3'
1248 SELECT me.book_id, me.author_id FROM book_authors me WHERE ( me.book_id = ? ): '4'
1249 SELECT me.book_id, me.author_id FROM book_authors me WHERE ( me.book_id = ? ): '5'
1251Also note in C<root/src/books/list.tt2> that we are using "| html", a
1252type of TT filter, to escape characters such as E<lt> and E<gt> to &lt;
1253and &gt; and avoid various types of dangerous hacks against your
1254application. In a real application, you would probably want to put
1255"| html" at the end of every field where a user has control over the
1256information that can appear in that field (and can therefore inject
1257markup or code if you don't "neutralize" those fields). In addition to
1258"| html", Template Toolkit has a variety of other useful filters that
1259can found in the documentation for
3533daff 1261
1265In some situations, it can be useful to run your application and
1266display a page without using a browser. Catalyst lets you do this
1267using the C<scripts/> script. Just supply the URL you
1268wish to display and it will run that request through the normal
1269controller dispatch logic and use the appropriate view to render the
1270output (obviously, complex pages may dump a lot of text to your
1271terminal window). For example, if you type:
1273 $ script/ "/books/list"
1275You should get the same text as if you visited
1276L<http://localhost:3000/books/list> with the normal development server
1277and asked your browser to view the page source.
3533daff 1278
1390ef0e 1279
1282B<NOTE: The rest of this part of the tutorial is optional. You can
1283skip to Part 4, L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>,
3533daff 1284if you wish.>
1390ef0e 1286=head2 Using C<RenderView> for the Default View
1288Once your controller logic has processed the request from a user, it
1289forwards processing to your view in order to generate the appropriate
3533daff 1290response output. Catalyst uses
1390ef0e 1291L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> by
1292default to automatically performs this operation. If you look in
1293C<lib/MyApp/Controller/>, you should see the empty
3533daff 1294definition for the C<sub end> method:
1296 sub end : ActionClass('RenderView') {}
1390ef0e 1298The following bullet points provide a quick overview of the
3533daff 1299C<RenderView> process:
1301=over 4
1303=item *
1305C<> is designed to hold application-wide logic.
1307=item *
1390ef0e 1309At the end of a given user request, Catalyst will call the most specific
1310C<end> method that's appropriate. For example, if the controller for a
1311request has an C<end> method defined, it will be called. However, if
1312the controller does not define a controller-specific C<end> method, the
3533daff 1313"global" C<end> method in C<> will be called.
1315=item *
1317Because the definition includes an C<ActionClass> attribute, the
1318L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> logic
1319will be executed B<after> any code inside the definition of C<sub end>
1320is run. See L<Catalyst::Manual::Actions|Catalyst::Manual::Actions>
1321for more information on C<ActionClass>.
1323=item *
1390ef0e 1325Because C<sub end> is empty, this effectively just runs the default
1326logic in C<RenderView>. However, you can easily extend the
1327C<RenderView> logic by adding your own code inside the empty method body
1328(C<{}>) created by the Catalyst Helpers when we first ran the
1329C<> to initialize our application. See
1330L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> for more
3533daff 1331detailed information on how to extended C<RenderView> in C<sub end>.
1336=head2 Using The Default Template Name
1390ef0e 1338By default, C<Catalyst::View::TT> will look for a template that uses the
1339same name as your controller action, allowing you to save the step of
1340manually specifying the template name in each action. For example, this
1341would allow us to remove the
1342C<$c-E<gt>stash-E<gt>{template} = 'books/list.tt2';> line of our
1343C<list> action in the Books controller. Open
3533daff 1344C<lib/MyApp/Controller/> in your editor and comment out this line
1345to match the following (only the C<$c-E<gt>stash-E<gt>{template}> line
1346has changed):
1348 =head2 list
1350 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
1352 =cut
1354 sub list : Local {
1355 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
1356 # 'Context' that's used to 'glue together' the various components
1357 # that make up the application
1358 my ($self, $c) = @_;
1360 # Retrieve all of the book records as book model objects and store in the
1361 # stash where they can be accessed by the TT template
d0496197 1362 $c->stash->{books} = [$c->model('DB::Books')->all];
3533daff 1363
1364 # Set the TT template to use. You will almost always want to do this
1365 # in your action methods (actions methods respond to user input in
1366 # your controllers).
1367 #$c->stash->{template} = 'books/list.tt2';
1368 }
3533daff 1370
1390ef0e 1371You should now be able to restart the development server as per the
3533daff 1372previous section and access the L<http://localhost:3000/books/list>
1373as before.
1375B<NOTE:> Please note that if you use the default template technique,
1376you will B<not> be able to use either the C<$c-E<gt>forward> or
1390ef0e 1377the C<$c-E<gt>detach> mechanisms (these are discussed in Part 2 and
3533daff 1378Part 9 of the Tutorial).
1381=head2 Return To A Manually-Specified Template
1383In order to be able to use C<$c-E<gt>forward> and C<$c-E<gt>detach>
1384later in the tutorial, you should remove the comment from the
1385statement in C<sub list> in C<lib/MyApp/Controller/>:
1387 $c->stash->{template} = 'books/list.tt2';
1390ef0e 1389Then delete the C<TEMPLATE_EXTENSION> line in
3533daff 1390C<lib/MyApp/View/>.
1390ef0e 1392You should then be able to restart the development server and
3533daff 1393access L<http://localhost:3000/books/list> in the same manner as
1394with earlier sections.
1397=head1 AUTHOR
1399Kennedy Clark, C<>
1401Please report any errors, issues or suggestions to the author. The
1402most recent version of the Catalyst Tutorial can be found at
82ab4bbf 1403L<>.
3533daff 1404
45c7830f 1405Copyright 2006-2008, Kennedy Clark, under Creative Commons License
8482d557 1406(L<>).