Fix minor typo
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / 03_MoreCatalystBasics.pod
CommitLineData
3533daff 1=head1 NAME
2
3ab6187c 3Catalyst::Manual::Tutorial::03_MoreCatalystBasics - Catalyst Tutorial - Chapter 3: More Catalyst Application Development Basics
3533daff 4
5
6=head1 OVERVIEW
7
4b4d3884 8This is B<Chapter 3 of 10> for the Catalyst tutorial.
3533daff 9
10L<Tutorial Overview|Catalyst::Manual::Tutorial>
11
12=over 4
13
14=item 1
15
3ab6187c 16L<Introduction|Catalyst::Manual::Tutorial::01_Intro>
3533daff 17
18=item 2
19
3ab6187c 20L<Catalyst Basics|Catalyst::Manual::Tutorial::02_CatalystBasics>
3533daff 21
22=item 3
23
3ab6187c 24B<03_More Catalyst Basics>
3533daff 25
26=item 4
27
3ab6187c 28L<Basic CRUD|Catalyst::Manual::Tutorial::04_BasicCRUD>
3533daff 29
30=item 5
31
3ab6187c 32L<Authentication|Catalyst::Manual::Tutorial::05_Authentication>
3533daff 33
34=item 6
35
3ab6187c 36L<Authorization|Catalyst::Manual::Tutorial::06_Authorization>
3533daff 37
38=item 7
39
3ab6187c 40L<Debugging|Catalyst::Manual::Tutorial::07_Debugging>
3533daff 41
42=item 8
43
3ab6187c 44L<Testing|Catalyst::Manual::Tutorial::08_Testing>
3533daff 45
46=item 9
47
3ab6187c 48L<Advanced CRUD|Catalyst::Manual::Tutorial::09_AdvancedCRUD>
3533daff 49
50=item 10
51
3ab6187c 52L<Appendices|Catalyst::Manual::Tutorial::10_Appendices>
3533daff 53
54=back
55
56
57=head1 DESCRIPTION
58
a8f4e284 59This chapter of the tutorial builds on the work done in Chapter 2 to
60explore some features that are more typical of "real world" web
61applications. From this chapter of the tutorial onward, we will be
62building a simple book database application. Although the application
63will be too limited to be of use to anyone, it should provide a basic
64environment where we can explore a variety of features used in virtually
65all web applications.
3533daff 66
4d63a0d5 67You can check out the source code for this example from the Catalyst
68Subversion repository as per the instructions in
2217b252 69L<Catalyst::Manual::Tutorial::01_Intro>.
3533daff 70
a8f4e284 71Please take a look at
72L<Catalyst::Manual::Tutorial::01_Intro/CATALYST INSTALLATION> before
73doing the rest of this tutorial. Although the tutorial should work
74correctly under most any recent version of Perl running on any operating
b9e431e3 75system, the tutorial has been written using Debian 6 and tested to be
a8f4e284 76sure it runs correctly in this environment.
a586a09f 77
3533daff 78
79=head1 CREATE A NEW APPLICATION
80
1390ef0e 81The remainder of the tutorial will build an application called C<MyApp>.
82First use the Catalyst C<catalyst.pl> script to initialize the framework
83for the C<MyApp> application (make sure you aren't still inside the
4b4d3884 84directory of the C<Hello> application from the previous chapter of the
acbd7bdd 85tutorial or in a directory that already has a "MyApp" subdirectory):
3533daff 86
87 $ catalyst.pl MyApp
88 created "MyApp"
89 created "MyApp/script"
90 created "MyApp/lib"
91 created "MyApp/root"
92 ...
93 created "MyApp/script/myapp_create.pl"
444d6b27 94 Change to application directory and Run "perl Makefile.PL" to make sure your install is complete
3533daff 95 $ cd MyApp
96
4b4d3884 97This creates a similar skeletal structure to what we saw in Chapter 2 of
a8f4e284 98the tutorial, except with C<MyApp> and C<myapp> substituted for C<Hello>
99and C<hello>. (As noted in Chapter 2, omit the ".pl" from the command
100if you are using Strawberry Perl.)
3533daff 101
102
103=head1 EDIT THE LIST OF CATALYST PLUGINS
104
a8f4e284 105One of the greatest benefits of Catalyst is that it has such a large
106library of bases classes and plugins available that you can use easily
107add functionality to your application. Plugins are used to seamlessly
108integrate existing Perl modules into the overall Catalyst framework. In
109general, they do this by adding additional methods to the C<context>
110object (generally written as C<$c>) that Catalyst passes to every
111component throughout the framework.
f058768a 112
3533daff 113
114By default, Catalyst enables three plugins/flags:
115
116=over 4
117
1390ef0e 118=item *
3533daff 119
120C<-Debug> Flag
121
122Enables the Catalyst debug output you saw when we started the
123C<script/myapp_server.pl> development server earlier. You can remove
79a529cc 124this item when you place your application into production.
3533daff 125
a8f4e284 126To be technically correct, it turns out that C<-Debug> is not a plugin,
127but a I<flag>. Although most of the items specified on the
128C<__PACKAGE__-E<gt>setup> line of your application class will be
129plugins, Catalyst supports a limited number of flag options (of these,
130C<-Debug> is the most common). See the documentation for C<Catalyst.pm>
131to get details on other flags (currently C<-Engine>, C<-Home>, and
132C<-Log>).
3533daff 133
444d6b27 134If you prefer, there are several other ways to enable debug output:
135
136=over 4
137
138=item *
139
140Use the C<$c-E<gt>debug> method
141
142=item *
143
144The C<-d> option to C<script/myapp_server.pl>
145
146=item *
147
148The C<CATALYST_DEBUG=1> environment variable (or set it to
433f1ad4 149zero to temporarily disable debug output).
444d6b27 150
151=back
3533daff 152
a8f4e284 153B<TIP>: Depending on your needs, it can be helpful to permanently remove
154C<-Debug> from C<lib/MyApp.pm> and then use the C<-d> option to
155C<script/myapp_server.pl> to re-enable it just for the development
1390ef0e 156server. We will not be using that approach in the tutorial, but feel
3533daff 157free to make use of it in your own projects.
158
159=item *
160
2217b252 161L<Catalyst::Plugin::ConfigLoader>
3533daff 162
163C<ConfigLoader> provides an automatic way to load configurable
c010ae0d 164parameters for your application from a central
2217b252 165L<Config::General> file (versus having the values
a8f4e284 166hard-coded inside your Perl modules). Config::General uses syntax very
167similar to Apache configuration files. We will see how to use this
168feature of Catalyst during the authentication and authorization sections
169(Chapter 5 and Chapter 6).
170
171B<IMPORTANT NOTE:> If you are using a version of
2217b252 172L<Catalyst::Devel> prior to version 1.06, be aware that
a8f4e284 173Catalyst changed the default format from YAML to the more
174straightforward C<Config::General> style. This tutorial uses the newer
175C<myapp.conf> file for C<Config::General>. However, Catalyst supports
176both formats and will automatically use either C<myapp.conf> or
177C<myapp.yml> (or any other format supported by
2217b252 178L<Catalyst::Plugin::ConfigLoader> and
179L<Config::Any>). If you are using a version of
a8f4e284 180Catalyst::Devel prior to 1.06, you can convert to the newer format by
181simply creating the C<myapp.conf> file manually and deleting
182C<myapp.yml>. The default contents of the C<myapp.conf> you create
183should only consist of one line:
1435672d 184
185 name MyApp
15e1d0b2 186
1390ef0e 187B<TIP>: This script can be useful for converting between configuration
15e1d0b2 188formats:
189
1390ef0e 190 perl -Ilib -e 'use MyApp; use Config::General;
15e1d0b2 191 Config::General->new->save_file("myapp.conf", MyApp->config);'
192
3533daff 193=item *
194
2217b252 195L<Catalyst::Plugin::Static::Simple>
3533daff 196
a8f4e284 197C<Static::Simple> provides an easy way to serve static content, such as
198images and CSS files, from the development server.
3533daff 199
200=back
201
a8f4e284 202For our application, we want to add one new plugin into the mix. To do
203this, edit C<lib/MyApp.pm> (this file is generally referred to as your
204I<application class>) and delete the lines with:
3533daff 205
1dc333c7 206 use Catalyst qw/
207 -Debug
208 ConfigLoader
209 Static::Simple
210 /;
3533daff 211
1390ef0e 212Then replace it with:
b411df01 213
acbd7bdd 214 # Load plugins
fce83e5f 215 use Catalyst qw/
1dc333c7 216 -Debug
217 ConfigLoader
218 Static::Simple
219
220 StackTrace
221 /;
1390ef0e 222
a8f4e284 223B<Note:> Recent versions of C<Catalyst::Devel> have used a variety of
224techniques to load these plugins/flags. For example, you might see the
225following:
94d8da41 226
acbd7bdd 227 __PACKAGE__->setup(qw/-Debug ConfigLoader Static::Simple/);
94d8da41 228
a8f4e284 229Don't let these variations confuse you -- they all accomplish the same
94d8da41 230result.
231
a8f4e284 232This tells Catalyst to start using one additional plugin,
233L<Catalyst::Plugin::StackTrace>, to add a stack trace to the standard
234Catalyst "debug screen" (the screen Catalyst sends to your browser when
235an error occurs). Be aware that
236L<StackTrace|Catalyst::Plugin::StackTrace> output appears in your
237browser, not in the console window from which you're running your
1390ef0e 238application, which is where logging output usually goes.
3533daff 239
444d6b27 240Make sure when adding new plugins you also include them as a new
a8f4e284 241dependency within the Makefile.PL file. For example, after adding the
242StackTrace plugin the Makefile.PL should include the following line:
3b1fa91b 243
244 requires 'Catalyst::Plugin::StackTrace';
245
246
a8f4e284 247B<Notes:>
3533daff 248
249=over 4
250
1390ef0e 251=item *
252
a8f4e284 253C<__PACKAGE__> is just a shorthand way of referencing the name of the
254package where it is used. Therefore, in C<MyApp.pm>, C<__PACKAGE__> is
255equivalent to C<MyApp>.
3533daff 256
1390ef0e 257=item *
3533daff 258
a8f4e284 259You will want to disable L<StackTrace|Catalyst::Plugin::StackTrace>
260before you put your application into production, but it can be helpful
1390ef0e 261during development.
3533daff 262
1390ef0e 263=item *
3533daff 264
a8f4e284 265When specifying plugins, you can omit C<Catalyst::Plugin::> from the
266name. Additionally, you can spread the plugin names across multiple
444d6b27 267lines as shown here or place them all on one line.
cca5cd98 268
3533daff 269=back
270
3533daff 271
272=head1 CREATE A CATALYST CONTROLLER
273
1390ef0e 274As discussed earlier, controllers are where you write methods that
275interact with user input. Typically, controller methods respond to
4d63a0d5 276C<GET> and C<POST> requests from the user's web browser.
3533daff 277
278Use the Catalyst C<create> script to add a controller for book-related
279actions:
280
281 $ script/myapp_create.pl controller Books
282 exists "/home/me/MyApp/script/../lib/MyApp/Controller"
283 exists "/home/me/MyApp/script/../t"
284 created "/home/me/MyApp/script/../lib/MyApp/Controller/Books.pm"
285 created "/home/me/MyApp/script/../t/controller_Books.t"
286
4b4d3884 287Then edit C<lib/MyApp/Controller/Books.pm> (as discussed in Chapter 2 of
1390ef0e 288the Tutorial, Catalyst has a separate directory under C<lib/MyApp> for
289each of the three parts of MVC: C<Model>, C<View>, and C<Controller>)
290and add the following method to the controller:
3533daff 291
292 =head2 list
293
294 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
295
296 =cut
1390ef0e 297
f058768a 298 sub list :Local {
3533daff 299 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
300 # 'Context' that's used to 'glue together' the various components
301 # that make up the application
302 my ($self, $c) = @_;
303
304 # Retrieve all of the book records as book model objects and store in the
305 # stash where they can be accessed by the TT template
0ed3df53 306 # $c->stash(books => [$c->model('DB::Book')->all]);
1390ef0e 307 # But, for now, use this code until we create the model later
0ed3df53 308 $c->stash(books => '');
1390ef0e 309
3533daff 310 # Set the TT template to use. You will almost always want to do this
311 # in your action methods (action methods respond to user input in
312 # your controllers).
61cb69fd 313 $c->stash(template => 'books/list.tt2');
3533daff 314 }
315
1390ef0e 316B<TIP>: See Appendix 1 for tips on removing the leading spaces when
317cutting and pasting example code from POD-based documents.
3533daff 318
a8f4e284 319Programmers experienced with object-oriented Perl should recognize
320C<$self> as a reference to the object where this method was called. On
321the other hand, C<$c> will be new to many Perl programmers who have not
322used Catalyst before (it's sometimes written as C<$context>). The
323Context object is automatically passed to all Catalyst components. It
324is used to pass information between components and provide access to
1390ef0e 325Catalyst and plugin functionality.
3533daff 326
a8f4e284 327Catalyst actions are regular Perl methods, but they make use of
328attributes (the "C<:Local>" next to the "C<sub list>" in the code above)
329to provide additional information to the Catalyst dispatcher logic (note
330that the space between the colon and the attribute name is optional; you
331will see attributes written both ways). Most Catalyst Controllers use
332one of five action types:
0416017e 333
334=over 4
335
336=item *
337
a8f4e284 338B<:Private> -- Use C<:Private> for methods that you want to make into an
339action, but you do not want Catalyst to directly expose the method to
340your users. Catalyst will not map C<:Private> methods to a URI. Use
341them for various sorts of "special" methods (the C<begin>, C<auto>, etc.
342discussed below) or for methods you want to be able to C<forward> or
343C<detach> to. (If the method is a plain old "helper method" that you
344don't want to be an action at all, then just define the method without
345any attribute -- you can call it in your code, but the Catalyst
346dispatcher will ignore it.)
0416017e 347
8fd01b0e 348There are five types of "special" built-in C<:Private> actions:
245b41d1 349C<begin>, C<end>, C<default>, C<index>, and C<auto>.
0416017e 350
26c9cad5 351=over 4
352
0416017e 353=item *
354
355With C<begin>, C<end>, C<default>, C<index> private actions, only the
356most specific action of each type will be called. For example, if you
357define a C<begin> action in your controller it will I<override> a
358C<begin> action in your application/root controller -- I<only> the
359action in your controller will be called.
360
361=item *
362
363Unlike the other actions where only a single method is called for each
364request, I<every> auto action along the chain of namespaces will be
365called. Each C<auto> action will be called I<from the application/root
366controller down through the most specific class>.
367
368=back
369
370=item *
371
a8f4e284 372B<:Path> -- C<:Path> actions let you map a method to an explicit URI
373path. For example, "C<:Path('list')>" in
374C<lib/MyApp/Controller/Books.pm> would match on the URL
375C<http://localhost:3000/books/list>, but "C<:Path('/list')>" would match
376on C<http://localhost:3000/list> (because of the leading slash). You
377can use C<:Args()> to specify how many arguments an action should
378accept. See L<Catalyst::Manual::Intro/Action_types> for more
444d6b27 379information and examples.
0416017e 380
381=item *
382
a8f4e284 383B<:Local> -- C<:Local> is merely a shorthand for
245b41d1 384"C<:Path('_name_of_method_')>". For example, these are equivalent:
a8f4e284 385"C<sub create_book :Local {...}>" and "C<sub create_book
386:Path('create_book') {...}>".
245b41d1 387
388=item *
389
a8f4e284 390B<:Global> -- C<:Global> is merely a shorthand for
245b41d1 391"C<:Path('/_name_of_method_')>". For example, these are equivalent:
a8f4e284 392"C<sub create_book :Global {...}>" and "C<sub create_book
393:Path('/create_book') {...}>".
245b41d1 394
395=item *
396
a8f4e284 397B<:Chained> -- Newer Catalyst applications tend to use the Chained
398dispatch form of action types because of its power and flexibility. It
399allows a series of controller methods to be automatically dispatched to
400service a single user request. See
2217b252 401L<Catalyst::Manual::Tutorial::04_BasicCRUD>
402and L<Catalyst::DispatchType::Chained>
0416017e 403for more information on chained actions.
404
405=back
406
a8f4e284 407You should refer to L<Catalyst::Manual::Intro/Action_types> for
408additional information and for coverage of some lesser-used action types
409not discussed here (C<Regex> and C<LocalRegex>).
3533daff 410
411
412=head1 CATALYST VIEWS
413
4d63a0d5 414As mentioned in Chapter 2 of the tutorial, views are where you render
415output, typically for display in the user's web browser (but also
416possibly using into output-generation systems, such as PDF or JSON).
417The code in C<lib/MyApp/View> selects the I<type> of view to use, with
418the actual rendering template found in the C<root> directory. As with
419virtually every aspect of Catalyst, options abound when it comes to the
420specific view technology you adopt inside your application. However,
421most Catalyst applications use the Template Toolkit, known as TT (for
422more information on TT, see L<http://www.template-toolkit.org>). Other
423somewhat popular view technologies include Mason
424(L<http://www.masonhq.com> and L<http://www.masonbook.com>) and
1390ef0e 425L<HTML::Template> (L<http://html-template.sourceforge.net>).
426
427
428=head2 Create a Catalyst View
3533daff 429
a8f4e284 430When using TT for the Catalyst view, the main helper script is
2217b252 431L<Catalyst::Helper::View::TT>. You may also
a8f4e284 432come across references to
2217b252 433L<Catalyst::Helper::View::TTSite>, but
a8f4e284 434its use is now deprecated.
1390ef0e 435
a8f4e284 436Enter the following command to enable the C<TT> style of view rendering
437for this tutorial:
3533daff 438
1edbdee6 439 $ script/myapp_create.pl view HTML TT
3533daff 440 exists "/home/me/MyApp/script/../lib/MyApp/View"
441 exists "/home/me/MyApp/script/../t"
1edbdee6 442 created "/home/me/MyApp/script/../lib/MyApp/View/HTML.pm"
443 created "/home/me/MyApp/script/../t/view_HTML.t"
444
a8f4e284 445This simply creates a view called C<HTML> in a file called C<HTML.pm>
446(the first argument). It is now up to you to decide how you want to
447structure your view layout. For the tutorial, we will start with a very
448simple TT template to initially demonstrate the concepts, but quickly
449migrate to a more typical "wrapper page" type of configuration (where
450the "wrapper" controls the overall "look and feel" of your site from a
451single file or set of files).
1edbdee6 452
a8f4e284 453Edit C<lib/MyApp/View/HTML.pm> and you should see something similar to
454the following:
3533daff 455
c062293d 456 __PACKAGE__->config(
457 TEMPLATE_EXTENSION => '.tt',
458 render_die => 1,
459 );
3533daff 460
1390ef0e 461And update it to match:
462
463 __PACKAGE__->config(
464 # Change default TT extension
465 TEMPLATE_EXTENSION => '.tt2',
c062293d 466 render_die => 1,
467 );
468
469This changes the default extension for Template Toolkit from '.tt' to
470'.tt2'.
471
a8f4e284 472You can also configure components in your application class. For
473example, Edit C<lib/MyApp.pm> and you should see that the default:
c062293d 474
475 __PACKAGE__->setup;
476
477Above this, add config:
478
479 __PACKAGE__->config(
480 'View::HTML' => {
481 #Set the location for TT files
482 INCLUDE_PATH => [
483 __PACKAGE__->path_to( 'root', 'src' ),
1390ef0e 484 ],
c062293d 485 },
1390ef0e 486 );
c062293d 487 # This line was here already
488 __PACKAGE__->setup;
3533daff 489
a8f4e284 490This changes the base directory for your template files from C<root> to
491C<root/src>.
1390ef0e 492
a8f4e284 493The reason to do this outside the C<lib/MyApp/View/HTML.pm> file is that
494the template path is found with the C<path_to> method, to get a path
495relative to the application root (no matter where it is installed), but
496this requires the application to be loaded...
c062293d 497
a8f4e284 498Trying to set this setting in the view means that you have a chicken and
499egg problem, in that the view requires the application to be loaded, but
500loading the application loads the view.
c062293d 501
502Putting the configuration which depends on the application class into
503that class is the neatest way to avoid this issue.
504
a8f4e284 505Please stick with the settings above for the duration of the tutorial,
506but feel free to use whatever options you desire in your applications
507(as with most things Perl, there's more than one way to do it...).
1390ef0e 508
a8f4e284 509B<Note:> We will use C<root/src> as the base directory for our template
510files, with a full naming convention of
511C<root/src/_controller_name_/_action_name_.tt2>. Another popular option
512is to use C<root/> as the base (with a full filename pattern of
acbd7bdd 513C<root/_controller_name_/_action_name_.tt2>).
514
a8f4e284 515
1390ef0e 516=head2 Create a TT Template Page
3533daff 517
518First create a directory for book-related TT templates:
519
1390ef0e 520 $ mkdir -p root/src/books
3533daff 521
522Then create C<root/src/books/list.tt2> in your editor and enter:
523
524 [% # This is a TT comment. The '-' at the end "chomps" the newline. You won't -%]
525 [% # see this "chomping" in your browser because HTML ignores blank lines, but -%]
526 [% # it WILL eliminate a blank line if you view the HTML source. It's purely -%]
527 [%- # optional, but both the beginning and the ending TT tags support chomping. -%]
528
1390ef0e 529 [% # Provide a title -%]
3533daff 530 [% META title = 'Book List' -%]
531
532 <table>
533 <tr><th>Title</th><th>Rating</th><th>Author(s)</th></tr>
534 [% # Display each book in a table row %]
535 [% FOREACH book IN books -%]
536 <tr>
537 <td>[% book.title %]</td>
538 <td>[% book.rating %]</td>
a46b474e 539 <td></td>
3533daff 540 </tr>
541 [% END -%]
542 </table>
543
544As indicated by the inline comments above, the C<META title> line uses
1390ef0e 545TT's META feature to provide a title to the "wrapper" that we will
546create later. Meanwhile, the C<FOREACH> loop iterates through each
547C<book> model object and prints the C<title> and C<rating> fields.
3533daff 548
4d63a0d5 549The C<[%> and C<%]> tags are used to delimit Template Toolkit code. TT
550supports a wide variety of directives for "calling" other files,
551looping, conditional logic, etc. In general, TT simplifies the usual
444d6b27 552range of Perl operators down to the single dot (".") operator. This
4d63a0d5 553applies to operations as diverse as method calls, hash lookups, and list
554index values (see
a8f4e284 555L<https://metacpan.org/module/Template::Manual::Variables> for details
556and examples). In addition to the usual L<Template> module Pod
4d63a0d5 557documentation, you can access the TT manual at
8c848468 558L<https://metacpan.org/module/Template::Manual>.
3533daff 559
a8f4e284 560B<TIP:> While you can build all sorts of complex logic into your TT
561templates, you should in general keep the "code" part of your templates
562as simple as possible. If you need more complex logic, create helper
563methods in your model that abstract out a set of code into a single call
564from your TT template. (Note that the same is true of your controller
565logic as well -- complex sections of code in your controllers should
566often be pulled out and placed into your model objects.) In Chapter 4
567of the tutorial we will explore some extremely helpful and powerful
568features of L<DBIx::Class> that allow you to pull code out of your views
569and controllers and place it where it rightfully belongs in a model
570class.
1390ef0e 571
572
573=head2 Test Run The Application
574
575To test your work so far, first start the development server:
576
f058768a 577 $ script/myapp_server.pl -r
1390ef0e 578
a8f4e284 579Then point your browser to L<http://localhost:3000> and you should still
580get the Catalyst welcome page. Next, change the URL in your browser to
581L<http://localhost:3000/books/list>. If you have everything working so
582far, you should see a web page that displays nothing other than our
583column headers for "Title", "Rating", and "Author(s)" -- we will not see
584any books until we get the database and model working below.
1390ef0e 585
586If you run into problems getting your application to run correctly, it
587might be helpful to refer to some of the debugging techniques covered in
fce83e5f 588the L<Debugging|Catalyst::Manual::Tutorial::07_Debugging> chapter of the
1390ef0e 589tutorial.
3533daff 590
591
592=head1 CREATE A SQLITE DATABASE
593
594In this step, we make a text file with the required SQL commands to
a8f4e284 595create a database table and load some sample data. We will use SQLite
596(L<http://www.sqlite.org>), a popular database that is lightweight and
597easy to use. Be sure to get at least version 3. Open C<myapp01.sql> in
598your editor and enter:
3533daff 599
600 --
601 -- Create a very simple database to hold book and author information
602 --
f058768a 603 PRAGMA foreign_keys = ON;
3b1fa91b 604 CREATE TABLE book (
3533daff 605 id INTEGER PRIMARY KEY,
606 title TEXT ,
607 rating INTEGER
608 );
3b1fa91b 609 -- 'book_author' is a many-to-many join table between books & authors
610 CREATE TABLE book_author (
b66dd084 611 book_id INTEGER REFERENCES book(id) ON DELETE CASCADE ON UPDATE CASCADE,
612 author_id INTEGER REFERENCES author(id) ON DELETE CASCADE ON UPDATE CASCADE,
3533daff 613 PRIMARY KEY (book_id, author_id)
614 );
3b1fa91b 615 CREATE TABLE author (
3533daff 616 id INTEGER PRIMARY KEY,
617 first_name TEXT,
618 last_name TEXT
619 );
620 ---
621 --- Load some sample data
622 ---
3b1fa91b 623 INSERT INTO book VALUES (1, 'CCSP SNRS Exam Certification Guide', 5);
624 INSERT INTO book VALUES (2, 'TCP/IP Illustrated, Volume 1', 5);
625 INSERT INTO book VALUES (3, 'Internetworking with TCP/IP Vol.1', 4);
626 INSERT INTO book VALUES (4, 'Perl Cookbook', 5);
627 INSERT INTO book VALUES (5, 'Designing with Web Standards', 5);
628 INSERT INTO author VALUES (1, 'Greg', 'Bastien');
629 INSERT INTO author VALUES (2, 'Sara', 'Nasseh');
630 INSERT INTO author VALUES (3, 'Christian', 'Degu');
631 INSERT INTO author VALUES (4, 'Richard', 'Stevens');
632 INSERT INTO author VALUES (5, 'Douglas', 'Comer');
633 INSERT INTO author VALUES (6, 'Tom', 'Christiansen');
634 INSERT INTO author VALUES (7, 'Nathan', 'Torkington');
635 INSERT INTO author VALUES (8, 'Jeffrey', 'Zeldman');
636 INSERT INTO book_author VALUES (1, 1);
637 INSERT INTO book_author VALUES (1, 2);
638 INSERT INTO book_author VALUES (1, 3);
639 INSERT INTO book_author VALUES (2, 4);
640 INSERT INTO book_author VALUES (3, 5);
641 INSERT INTO book_author VALUES (4, 6);
642 INSERT INTO book_author VALUES (4, 7);
643 INSERT INTO book_author VALUES (5, 8);
3533daff 644
3533daff 645Then use the following command to build a C<myapp.db> SQLite database:
646
647 $ sqlite3 myapp.db < myapp01.sql
648
649If you need to create the database more than once, you probably want to
650issue the C<rm myapp.db> command to delete the database before you use
1390ef0e 651the C<sqlite3 myapp.db E<lt> myapp01.sql> command.
3533daff 652
653Once the C<myapp.db> database file has been created and initialized, you
654can use the SQLite command line environment to do a quick dump of the
655database contents:
656
657 $ sqlite3 myapp.db
f058768a 658 SQLite version 3.6.22
3533daff 659 Enter ".help" for instructions
f058768a 660 Enter SQL statements terminated with a ";"
3b1fa91b 661 sqlite> select * from book;
3533daff 662 1|CCSP SNRS Exam Certification Guide|5
663 2|TCP/IP Illustrated, Volume 1|5
664 3|Internetworking with TCP/IP Vol.1|4
665 4|Perl Cookbook|5
666 5|Designing with Web Standards|5
667 sqlite> .q
668 $
669
670Or:
671
3b1fa91b 672 $ sqlite3 myapp.db "select * from book"
3533daff 673 1|CCSP SNRS Exam Certification Guide|5
674 2|TCP/IP Illustrated, Volume 1|5
675 3|Internetworking with TCP/IP Vol.1|4
676 4|Perl Cookbook|5
677 5|Designing with Web Standards|5
678
679As with most other SQL tools, if you are using the full "interactive"
680environment you need to terminate your SQL commands with a ";" (it's not
681required if you do a single SQL statement on the command line). Use
682".q" to exit from SQLite from the SQLite interactive mode and return to
683your OS command prompt.
684
a8f4e284 685Please note that here we have chosen to use 'singular' table names. This
686is because the default inflection code for older versions of
687L<DBIx::Class::Schema::Loader> does NOT handle plurals. There has been
688much philosophical discussion on whether table names should be plural or
689singular. There is no one correct answer, as long as one makes a choice
690and remains consistent with it. If you prefer plural table names (e.g.
691you think that they are easier to read) then see the documentation in
658b8c29 692L<DBIx::Class::Schema::Loader::Base/naming> (version 0.05 or greater).
3b1fa91b 693
a8f4e284 694For using other databases, such as PostgreSQL or MySQL, see
3ab6187c 695L<Appendix 2|Catalyst::Manual::Tutorial::10_Appendices>.
3533daff 696
acbd7bdd 697
8a472b34 698=head1 DATABASE ACCESS WITH DBIx::Class
3533daff 699
a8f4e284 700Catalyst can be used with virtually any form of datastore available via
2217b252 701Perl. For example, L<Catalyst::Model::DBI> can be
a8f4e284 702used to access databases through the traditional Perl L<DBI> interface
703or you can use a model to access files of any type on the filesystem.
704However, most Catalyst applications use some form of object-relational
705mapping (ORM) technology to create objects associated with tables in a
2217b252 706relational database. Matt Trout's L<DBIx::Class>
a8f4e284 707(abbreviated as "DBIC") has rapidly emerged as the Perl-based ORM
708technology of choice. Most new Catalyst applications rely on
709DBIx::Class, as will this tutorial.
710
711Although DBIx::Class has included support for a C<create=dynamic> mode
712to automatically read the database structure every time the application
713starts, its use is no longer recommended. While it can make for
714"flashy" demos, the use of the C<create=static> mode we use below can be
715implemented just as quickly and provides many advantages (such as the
716ability to add your own methods to the overall DBIC framework, a
717technique that we see in Chapter 4).
3533daff 718
1390ef0e 719
a46b474e 720=head2 Make Sure You Have a Recent Version of the DBIx::Class Model
27909ed4 721
722First, let's be sure we have a recent version of the DBIC helper,
a8f4e284 723L<Catalyst::Model::DBIC::Schema>, so that we can take advantage of some
724recent enhancements in how foreign keys are handled with SQLite. To
725check your version, run this command:
27909ed4 726
727 $ perl -MCatalyst::Model::DBIC::Schema -e \
728 'print "$Catalyst::Model::DBIC::Schema::VERSION\n"'
f33d1dd7 729 0.4
27909ed4 730
a8f4e284 731Please note the '\' above. Depending on your environment, you might be
732able to cut and paste the text as shown or need to remove the '\'
fce83e5f 733character to that the command is all on a single line.
3b1fa91b 734
b9e431e3 735If you are following along in Debian 6, you should have version 0.40 or
a8f4e284 736higher (shown above as "0.4" with the tailing zero removed). If you have
737less than v0.39, you will need to run this command to install it
738directly from CPAN:
27909ed4 739
3e008853 740 $ cpan -i Catalyst::Model::DBIC::Schema
27909ed4 741
a8f4e284 742And re-run the version print command to verify that you are now at 0.39
743or higher.
f058768a 744
745In addition, since we are using SQLite's foreign key support here,
746please be sure that you use version C<1.27> of L<DBD::SQLite> or later:
747
748 $ perl -MDBD::SQLite -e 'print "$DBD::SQLite::VERSION\n"'
749 1.29
750
751Upgrade if you are not at version C<1.27> or higher.
27909ed4 752
a8f4e284 753Also, remember to put a line requiring the version of the module you
754just installed into your Makefile.PL
27909ed4 755
a46b474e 756=head2 Create Static DBIx::Class Schema Files
27909ed4 757
a8f4e284 758Before you continue, make sure your C<myapp.db> database file is in the
759application's topmost directory. Now use the model helper with the
760C<create=static> option to read the database with
2217b252 761L<DBIx::Class::Schema::Loader> and
27909ed4 762automatically build the required files for us:
3533daff 763
4ab6212d 764 $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
b66dd084 765 create=static dbi:SQLite:myapp.db \
766 on_connect_do="PRAGMA foreign_keys = ON"
1390ef0e 767 exists "/home/me/MyApp/script/../lib/MyApp/Model"
768 exists "/home/me/MyApp/script/../t"
27909ed4 769 Dumping manual schema for MyApp::Schema to directory /home/me/MyApp/script/../lib ...
770 Schema dump completed.
1390ef0e 771 created "/home/me/MyApp/script/../lib/MyApp/Model/DB.pm"
772 created "/home/me/MyApp/script/../t/model_DB.t"
3533daff 773
a8f4e284 774Please note the '\' above. Depending on your environment, you might be
775able to cut and paste the text as shown or need to remove the '\'
fce83e5f 776character to that the command is all on a single line.
3b1fa91b 777
27909ed4 778The C<script/myapp_create.pl> command breaks down like this:
779
780=over 4
781
782=item *
783
a8f4e284 784C<DB> is the name of the model class to be created by the helper in
27909ed4 785C<lib/MyApp/Model>.
786
787=item *
788
789C<DBIC::Schema> is the type of the model to create.
790
791=item *
792
793C<MyApp::Schema> is the name of the DBIC schema file written to
794C<lib/MyApp/Schema.pm>.
795
796=item *
797
a8f4e284 798C<create=static> causes
2217b252 799L<DBIx::Class::Schema::Loader> to load the
a8f4e284 800schema as it runs and then write that information out into files.
27909ed4 801
802=item *
803
a8f4e284 804C<dbi:SQLite:myapp.db> is the standard DBI connect string for use with
805SQLite.
27909ed4 806
f058768a 807=item *
808
a8f4e284 809And finally, the C<on_connect_do> string requests that
2217b252 810L<DBIx::Class::Schema::Loader> create
a8f4e284 811foreign key relationships for us (this is not needed for databases such
812as PostgreSQL and MySQL, but is required for SQLite). If you take a look
813at C<lib/MyApp/Model/DB.pm>, you will see that the SQLite pragma is
814propogated to the Model, so that SQLite's recent (and optional) foreign
815key enforcement is enabled at the start of every database connection.
f058768a 816
817
27909ed4 818=back
819
a8f4e284 820If you look in the C<lib/MyApp/Schema.pm> file, you will find that it
821only contains a call to the C<load_namespaces> method. You will also
822find that C<lib/MyApp> contains a C<Schema> subdirectory, which then has
823a subdirectory called "Result". This "Result" subdirectory then has
824files named according to each of the tables in our simple database
825(C<Author.pm>, C<BookAuthor.pm>, and C<Book.pm>). These three files are
826called "Result Classes" in DBIx::Class nomenclature. Although the Result
827Class files are named after tables in our database, the classes
828correspond to the I<row-level data> that is returned by DBIC (more on
829this later, especially in
3ab6187c 830L<Catalyst::Manual::Tutorial::04_BasicCRUD/EXPLORING THE POWER OF DBIC>).
27909ed4 831
a8f4e284 832The idea with the Result Source files created under
833C<lib/MyApp/Schema/Result> by the C<create=static> option is to only
834edit the files below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!>
835warning. If you place all of your changes below that point in the file,
836you can regenerate the automatically created information at the top of
837each file should your database structure get updated.
838
839Also note the "flow" of the model information across the various files
840and directories. Catalyst will initially load the model from
841C<lib/MyApp/Model/DB.pm>. This file contains a reference to
842C<lib/MyApp/Schema.pm>, so that file is loaded next. Finally, the call
843to C<load_namespaces> in C<Schema.pm> will load each of the "Result
844Class" files from the C<lib/MyApp/Schema/Result> subdirectory. The
845final outcome is that Catalyst will dynamically create three
846table-specific Catalyst models every time the application starts (you
847can see these three model files listed in the debug output generated
27909ed4 848when you launch the application).
849
a8f4e284 850B<NOTE:> Older versions of
2217b252 851L<Catalyst::Model::DBIC::Schema> use the
a8f4e284 852deprecated DBIx::Class C<load_classes> technique instead of the newer
853C<load_namespaces>. For new applications, please try to use
854C<load_namespaces> since it more easily supports a very useful DBIC
855technique called "ResultSet Classes." If you need to convert an
856existing application from "load_classes" to "load_namespaces," you can
b66dd084 857use this process to automate the migration, but first make sure you have
858version C<0.39> of L<Catalyst::Model::DBIC::Schema> and
859L<DBIx::Class::Schema::Loader> version C<0.05000> or later.
27909ed4 860
b66dd084 861 $ # Re-run the helper to upgrade for you
27909ed4 862 $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
b66dd084 863 create=static naming=current use_namespaces=1 \
864 dbi:SQLite:myapp.db \
865 on_connect_do="PRAGMA foreign_keys = ON"
dc9a0503 866
f058768a 867
1390ef0e 868=head1 ENABLE THE MODEL IN THE CONTROLLER
869
a8f4e284 870Open C<lib/MyApp/Controller/Books.pm> and un-comment the model code we
acbd7bdd 871left disabled earlier so that your version matches the following (un-
a8f4e284 872comment the line containing C<[$c-E<gt>model('DB::Book')-E<gt>all]> and
873delete the next 2 lines):
1390ef0e 874
875 =head2 list
876
877 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
878
879 =cut
880
f058768a 881 sub list :Local {
1390ef0e 882 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
883 # 'Context' that's used to 'glue together' the various components
884 # that make up the application
885 my ($self, $c) = @_;
886
f058768a 887 # Retrieve all of the book records as book model objects and store
888 # in the stash where they can be accessed by the TT template
0ed3df53 889 $c->stash(books => [$c->model('DB::Book')->all]);
1390ef0e 890
891 # Set the TT template to use. You will almost always want to do this
892 # in your action methods (action methods respond to user input in
893 # your controllers).
61cb69fd 894 $c->stash(template => 'books/list.tt2');
1390ef0e 895 }
896
a8f4e284 897B<TIP>: You may see the C<$c-E<gt>model('DB::Book')> un-commented above
898written as C<$c-E<gt>model('DB')-E<gt>resultset('Book')>. The two are
899equivalent. Either way, C<$c-E<gt>model> returns a
2217b252 900L<DBIx::Class::ResultSet> which handles queries
a8f4e284 901against the database and iterating over the set of results that is
c93b5eaa 902returned.
903
a8f4e284 904We are using the C<-E<gt>all> to fetch all of the books. DBIC supports
905a wide variety of more advanced operations to easily do things like
906filtering and sorting the results. For example, the following could be
907used to sort the results by descending title:
c93b5eaa 908
3b1fa91b 909 $c->model('DB::Book')->search({}, {order_by => 'title DESC'});
c93b5eaa 910
a8f4e284 911Some other examples are provided in
912L<DBIx::Class::Manual::Cookbook/Complex WHERE clauses>, with additional
913information found at L<DBIx::Class::ResultSet/search>,
914L<DBIx::Class::Manual::FAQ/Searching>,
2217b252 915L<DBIx::Class::Manual::Intro> and
916L<Catalyst::Model::DBIC::Schema>.
1390ef0e 917
918
919=head2 Test Run The Application
3533daff 920
a8f4e284 921First, let's enable an environment variable that causes DBIx::Class to
922dump the SQL statements used to access the database. This is a helpful
923trick when you are trying to debug your database-oriented code. Press
924C<Ctrl-C> to break out of the development server and enter:
3533daff 925
926 $ export DBIC_TRACE=1
f058768a 927 $ script/myapp_server.pl -r
f33d1dd7 928
4d63a0d5 929This assumes you are using bash as your shell -- adjust accordingly if
3533daff 930you are using a different shell (for example, under tcsh, use
931C<setenv DBIC_TRACE 1>).
932
d0496197 933B<NOTE:> You can also set this in your code using
3533daff 934C<$class-E<gt>storage-E<gt>debug(1);>. See
935L<DBIx::Class::Manual::Troubleshooting> for details (including options
a8f4e284 936to log to a file instead of displaying to the Catalyst development
937server log).
3533daff 938
1390ef0e 939Then launch the Catalyst development server. The log output should
940display something like:
3533daff 941
f058768a 942 $ script/myapp_server.pl -r
3533daff 943 [debug] Debug messages enabled
1390ef0e 944 [debug] Statistics enabled
3533daff 945 [debug] Loaded plugins:
946 .----------------------------------------------------------------------------.
a467a714 947 | Catalyst::Plugin::ConfigLoader 0.27 |
948 | Catalyst::Plugin::StackTrace 0.11 |
3533daff 949 '----------------------------------------------------------------------------'
950
951 [debug] Loaded dispatcher "Catalyst::Dispatcher"
952 [debug] Loaded engine "Catalyst::Engine::HTTP"
953 [debug] Found home "/home/me/MyApp"
45d511e0 954 [debug] Loaded Config "/home/me/MyApp/myapp.conf"
3533daff 955 [debug] Loaded components:
956 .-----------------------------------------------------------------+----------.
957 | Class | Type |
958 +-----------------------------------------------------------------+----------+
959 | MyApp::Controller::Books | instance |
960 | MyApp::Controller::Root | instance |
d0496197 961 | MyApp::Model::DB | instance |
3b1fa91b 962 | MyApp::Model::DB::Author | class |
963 | MyApp::Model::DB::Book | class |
964 | MyApp::Model::DB::BookAuthor | class |
1edbdee6 965 | MyApp::View::HTML | instance |
3533daff 966 '-----------------------------------------------------------------+----------'
967
968 [debug] Loaded Private actions:
969 .----------------------+--------------------------------------+--------------.
970 | Private | Class | Method |
971 +----------------------+--------------------------------------+--------------+
972 | /default | MyApp::Controller::Root | default |
973 | /end | MyApp::Controller::Root | end |
1390ef0e 974 | /index | MyApp::Controller::Root | index |
3533daff 975 | /books/index | MyApp::Controller::Books | index |
976 | /books/list | MyApp::Controller::Books | list |
977 '----------------------+--------------------------------------+--------------'
978
979 [debug] Loaded Path actions:
980 .-------------------------------------+--------------------------------------.
981 | Path | Private |
982 +-------------------------------------+--------------------------------------+
1390ef0e 983 | / | /default |
984 | / | /index |
985 | /books | /books/index |
3533daff 986 | /books/list | /books/list |
987 '-------------------------------------+--------------------------------------'
988
f058768a 989 [info] MyApp powered by Catalyst 5.80020
acbd7bdd 990 You can connect to your server at http://debian:3000
3533daff 991
a8f4e284 992B<NOTE:> Be sure you run the C<script/myapp_server.pl> command from the
993'base' directory of your application, not inside the C<script> directory
994itself or it will not be able to locate the C<myapp.db> database file.
995You can use a fully qualified or a relative path to locate the database
996file, but we did not specify that when we ran the model helper earlier.
3533daff 997
998Some things you should note in the output above:
999
1000=over 4
1001
1390ef0e 1002=item *
3533daff 1003
1390ef0e 1004Catalyst::Model::DBIC::Schema dynamically created three model classes,
1005one to represent each of the three tables in our database
a8f4e284 1006(C<MyApp::Model::DB::Author>, C<MyApp::Model::DB::BookAuthor>, and
1007C<MyApp::Model::DB::Book>).
3533daff 1008
1390ef0e 1009=item *
3533daff 1010
1011The "list" action in our Books controller showed up with a path of
1012C</books/list>.
1013
1014=back
1015
1016Point your browser to L<http://localhost:3000> and you should still get
1017the Catalyst welcome page.
1018
1019Next, to view the book list, change the URL in your browser to
1020L<http://localhost:3000/books/list>. You should get a list of the five
1390ef0e 1021books loaded by the C<myapp01.sql> script above without any formatting.
1022The rating for each book should appear on each row, but the "Author(s)"
191dee29 1023column will still be blank (we will fill that in later).
3533daff 1024
a8f4e284 1025Also notice in the output of the C<script/myapp_server.pl> that
a46b474e 1026DBIx::Class used the following SQL to retrieve the data:
3533daff 1027
fce83e5f 1028 SELECT me.id, me.title, me.rating FROM book me
3533daff 1029
1030because we enabled DBIC_TRACE.
1031
0c51850e 1032You now have the beginnings of a simple but workable web application.
a8f4e284 1033Continue on to future sections and we will develop the application more
1034fully.
3533daff 1035
1036
1390ef0e 1037=head1 CREATE A WRAPPER FOR THE VIEW
1038
a8f4e284 1039When using TT, you can (and should) create a wrapper that will literally
1040wrap content around each of your templates. This is certainly useful as
1041you have one main source for changing things that will appear across
1042your entire site/application instead of having to edit many individual
1043files.
1390ef0e 1044
1045
1edbdee6 1046=head2 Configure HTML.pm For The Wrapper
1390ef0e 1047
a8f4e284 1048In order to create a wrapper, you must first edit your TT view and tell
1049it where to find your wrapper file.
1390ef0e 1050
a8f4e284 1051Edit your TT view in C<lib/MyApp/View/HTML.pm> and change it to match
1052the following:
1390ef0e 1053
1054 __PACKAGE__->config(
1055 # Change default TT extension
1056 TEMPLATE_EXTENSION => '.tt2',
1057 # Set the location for TT files
1058 INCLUDE_PATH => [
c2dfb562 1059 MyApp->path_to( 'root', 'src' ),
1390ef0e 1060 ],
1061 # Set to 1 for detailed timer stats in your HTML as comments
1062 TIMER => 0,
1063 # This is your wrapper template located in the 'root/src'
1064 WRAPPER => 'wrapper.tt2',
1065 );
1066
1067
1068=head2 Create the Wrapper Template File and Stylesheet
1069
1070Next you need to set up your wrapper template. Basically, you'll want
a8f4e284 1071to take the overall layout of your site and put it into this file. For
1072the tutorial, open C<root/src/wrapper.tt2> and input the following:
1390ef0e 1073
1074 <?xml version="1.0" encoding="UTF-8"?>
1075 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
1076 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1077 <head>
1078 <title>[% template.title or "My Catalyst App!" %]</title>
1079 <link rel="stylesheet" href="[% c.uri_for('/static/css/main.css') %]" />
1080 </head>
1081
1082 <body>
1083 <div id="outer">
1084 <div id="header">
1085 [%# Your logo could go here -%]
1086 <img src="[% c.uri_for('/static/images/btn_88x31_powered.png') %]" />
1087 [%# Insert the page title -%]
1088 <h1>[% template.title or site.title %]</h1>
1089 </div>
1090
1091 <div id="bodyblock">
1092 <div id="menu">
1093 Navigation:
1094 <ul>
1095 <li><a href="[% c.uri_for('/books/list') %]">Home</a></li>
1096 <li><a href="[% c.uri_for('/') %]" title="Catalyst Welcome Page">Welcome</a></li>
1390ef0e 1097 </ul>
1098 </div><!-- end menu -->
1099
1100 <div id="content">
1101 [%# Status and error messages %]
1102 <span class="message">[% status_msg %]</span>
1103 <span class="error">[% error_msg %]</span>
1104 [%# This is where TT will stick all of your template's contents. -%]
1105 [% content %]
1106 </div><!-- end content -->
1107 </div><!-- end bodyblock -->
1108
1109 <div id="footer">Copyright (c) your name goes here</div>
c2dfb562 1110 </div><!-- end outer -->
1390ef0e 1111
1112 </body>
1113 </html>
1114
1115Notice the status and error message sections in the code above:
1116
1117 <span class="status">[% status_msg %]</span>
1118 <span class="error">[% error_msg %]</span>
1119
1120If we set either message in the Catalyst stash (e.g.,
a8f4e284 1121C<$c-E<gt>stash-E<gt>{status_msg} = 'Request was successful!'>) it will
1122be displayed whenever any view used by that request is rendered. The
1123C<message> and C<error> CSS styles can be customized to suit your needs
1124in the C<root/static/css/main.css> file we create below.
1390ef0e 1125
a8f4e284 1126B<Notes:>
1390ef0e 1127
1128=over 4
1129
1130=item *
1131
a8f4e284 1132The Catalyst stash only lasts for a single HTTP request. If you need to
1133retain information across requests you can use
2217b252 1134L<Catalyst::Plugin::Session> (we will use
4b4d3884 1135Catalyst sessions in the Authentication chapter of the tutorial).
1390ef0e 1136
1137=item *
1138
a8f4e284 1139Although it is beyond the scope of this tutorial, you may wish to use a
1140JavaScript or AJAX tool such as jQuery (L<http://www.jquery.com>) or
1390ef0e 1141Dojo (L<http://www.dojotoolkit.org>).
1142
1143=back
1144
1145
1146=head3 Create A Basic Stylesheet
1147
1148First create a central location for stylesheets under the static
1149directory:
1150
1151 $ mkdir root/static/css
1152
1153Then open the file C<root/static/css/main.css> (the file referenced in
1154the stylesheet href link of our wrapper above) and add the following
1155content:
1156
1157 #header {
1158 text-align: center;
1159 }
1160 #header h1 {
1161 margin: 0;
1162 }
1163 #header img {
1164 float: right;
1165 }
1166 #footer {
1167 text-align: center;
1168 font-style: italic;
1169 padding-top: 20px;
1170 }
1171 #menu {
1172 font-weight: bold;
1173 background-color: #ddd;
1174 }
1175 #menu ul {
1176 list-style: none;
1177 float: left;
1178 margin: 0;
1179 padding: 0 0 50% 5px;
1180 font-weight: normal;
1181 background-color: #ddd;
1182 width: 100px;
1183 }
1184 #content {
1185 margin-left: 120px;
1186 }
1187 .message {
1188 color: #390;
1189 }
1190 .error {
1191 color: #f00;
1192 }
1193
1194You may wish to check out a "CSS Framework" like Emastic
a8f4e284 1195(L<http://code.google.com/p/emastic/>) as a way to quickly provide lots
1196of high-quality CSS functionality.
1390ef0e 1197
1198
1199=head2 Test Run The Application
1200
a8f4e284 1201Hit "Reload" in your web browser and you should now see a formatted
1202version of our basic book list. (Again, the development server should
1203have automatically restarted when you made changes to
1204C<lib/MyApp/View/HTML.pm>. If you are not using the "-r" option, you
1205will need to hit C<Ctrl-C> and manually restart it. Also note that the
1206development server does I<NOT> need to restart for changes to the TT and
1207static files we created and edited in the C<root> directory -- those
1208updates are handled on a per-request basis.)
f058768a 1209
a8f4e284 1210Although our wrapper and stylesheet are obviously very simple, you
1211should see how it allows us to control the overall look of an entire
1212website from two central files. To add new pages to the site, just
1213provide a template that fills in the C<content> section of our wrapper
1214template -- the wrapper will provide the overall feel of the page.
1390ef0e 1215
1216
a46b474e 1217=head2 Updating the Generated DBIx::Class Result Class Files
3533daff 1218
a8f4e284 1219If you take a look at the Schema files automatically generated by
1220L<DBIx::Class::Schema::Loader>, you will see that it has already defined
1221C<has_many> and C<belongs_to> relationships on each side of our foreign
1222keys. For example, take a look at C<lib/MyApp/Schema/Result/Book.pm> and
1223notice the following code:
f058768a 1224
1225 =head1 RELATIONS
1226
1227 =head2 book_authors
1228
1229 Type: has_many
1230
1231 Related object: L<MyApp::Schema::Result::BookAuthor>
1232
1233 =cut
1234
1235 __PACKAGE__->has_many(
1236 "book_authors",
1237 "MyApp::Schema::Result::BookAuthor",
1238 { "foreign.book_id" => "self.id" },
1239 );
1240
a8f4e284 1241Each C<Book> "has_many" C<book_authors>, where C<BookAuthor> is the
1242many-to-many table that allows each Book to have multiple Authors, and
1243each Author to have mulitple books. The arguments to C<has_many> are:
f058768a 1244
1245=over 4
1246
1247=item *
1248
a8f4e284 1249C<book_authors> - The name for this relationship. DBIC will create an
1250accessor on the C<Books> DBIC Row object with this name.
f058768a 1251
1252=item *
1253
a8f4e284 1254C<MyApp::Schema::Result::BookAuthor> - The name of the DBIC model class
1255referenced by this C<has_many> relationship.
f058768a 1256
1257=item *
1258
a8f4e284 1259C<foreign.book_id> - C<book_id> is the name of the foreign key column in
1260the I<foreign> table that points back to this table.
f058768a 1261
1262=item *
1263
a8f4e284 1264C<self.id> - C<id> is the name of the column in I<this> table that is
1265referenced by the foreign key.
f058768a 1266
1267=back
1268
a8f4e284 1269See L<DBIx::Class::Relationship/has_many> for additional information.
1270Note that you might see a "hand coded" version of the C<has_many>
1271relationship above expressed as:
f058768a 1272
1273 __PACKAGE__->has_many(
1274 "book_authors",
1275 "MyApp::Schema::Result::BookAuthor",
1276 "book_id",
1277 );
1278
a8f4e284 1279Where the third argument is simply the name of the column in the foreign
1280table. However, the hashref syntax used by
1281L<DBIx::Class::Schema::Loader> is more flexible (for example, it can
1282handle "multi-column" foreign keys).
f058768a 1283
a8f4e284 1284B<Note:> If you are using older versions of SQLite and related DBIC
1285tools, you will need to manually define your C<has_many> and
1286C<belongs_to> relationships. We recommend upgrading to the versions
1287specified above. :-)
f058768a 1288
a8f4e284 1289Have a look at C<lib/MyApp/Schema/Result/BookAuthor.pm> and notice that
1290there is a C<belongs_to> relationship defined that acts as the "mirror
1291image" to the C<has_many> relationship we just looked at above:
f058768a 1292
1293 =head1 RELATIONS
1294
1295 =head2 book
1296
1297 Type: belongs_to
1298
1299 Related object: L<MyApp::Schema::Result::Book>
1300
1301 =cut
1302
1303 __PACKAGE__->belongs_to(
1304 "book",
1305 "MyApp::Schema::Result::Book",
1306 { id => "book_id" },
1307 { join_type => "LEFT" },
1308 );
1309
a8f4e284 1310The arguments are similar, but see
f058768a 1311L<DBIx::Class::Relationship/belongs_to> for the details.
f33d1dd7 1312
a8f4e284 1313Although recent versions of SQLite and L<DBIx::Class::Schema::Loader>
1314automatically handle the C<has_many> and C<belongs_to> relationships,
7040a6cd 1315C<many_to_many> relationship bridges (not technically a relationship)
a8f4e284 1316currently need to be manually inserted. To add a C<many_to_many>
1317relationship bridge, first edit C<lib/MyApp/Schema/Result/Book.pm> and
1318add the following text below the C<# You can replace this text...>
1319comment:
3533daff 1320
3533daff 1321 # many_to_many():
1322 # args:
7040a6cd 1323 # 1) Name of relationship bridge, DBIC will create accessor with this name
1390ef0e 1324 # 2) Name of has_many() relationship this many_to_many() is shortcut for
1325 # 3) Name of belongs_to() relationship in model class of has_many() above
3533daff 1326 # You must already have the has_many() defined to use a many_to_many().
fce83e5f 1327 __PACKAGE__->many_to_many(authors => 'book_authors', 'author');
3533daff 1328
a8f4e284 1329B<Note:> Be careful to put this code I<above> the C<1;> at the end of
1330the file. As with any Perl package, we need to end the last line with a
1331statement that evaluates to C<true>. This is customarily done with
3533daff 1332C<1;> on a line by itself.
1333
7040a6cd 1334The C<many_to_many> relationship bridge is optional, but it makes it
a8f4e284 1335easier to map a book to its collection of authors. Without it, we would
1336have to "walk" through the C<book_author> table as in
1337C<$book-E<gt>book_author-E<gt>first-E<gt>author-E<gt>last_name> (we will
1338see examples on how to use DBIx::Class objects in your code soon, but
1339note that because C<$book-E<gt>book_author> can return multiple authors,
1340we have to use C<first> to display a single author). C<many_to_many>
1341allows us to use the shorter
1342C<$book-E<gt>author-E<gt>first-E<gt>last_name>. Note that you cannot
1343define a C<many_to_many> relationship bridge without also having the
5a82cb36 1344C<has_many> relationship in place.
3533daff 1345
a8f4e284 1346Then edit C<lib/MyApp/Schema/Result/Author.pm> and add the reverse
1347C<many_to_many> relationship bridge for C<Author> as follows (again, be
1348careful to put in above the C<1;> but below the C<# DO NOT MODIFY THIS
1349OR ANYTHING ABOVE!> comment):
3533daff 1350
3533daff 1351 # many_to_many():
1352 # args:
7040a6cd 1353 # 1) Name of relationship bridge, DBIC will create accessor with this name
3533daff 1354 # 2) Name of has_many() relationship this many_to_many() is shortcut for
1390ef0e 1355 # 3) Name of belongs_to() relationship in model class of has_many() above
3533daff 1356 # You must already have the has_many() defined to use a many_to_many().
fce83e5f 1357 __PACKAGE__->many_to_many(books => 'book_authors', 'book');
3533daff 1358
f058768a 1359
1390ef0e 1360=head2 Run The Application
3533daff 1361
4d63a0d5 1362Run the Catalyst development server script with the C<DBIC_TRACE> option
1363(it might still be enabled from earlier in the tutorial, but here is an
f33d1dd7 1364alternate way to specify the trace option just in case):
3533daff 1365
f058768a 1366 $ DBIC_TRACE=1 script/myapp_server.pl -r
3533daff 1367
1390ef0e 1368Make sure that the application loads correctly and that you see the
a8f4e284 1369three dynamically created model class (one for each of the Result
1370Classes we created).
3533daff 1371
a8f4e284 1372Then hit the URL L<http://localhost:3000/books/list> with your browser
f33d1dd7 1373and be sure that the book list still displays correctly.
3533daff 1374
a8f4e284 1375B<Note:> You will not see the authors yet because the view does not yet
1376use the new relations. Read on to the next section where we update the
c2dfb562 1377template to do that.
3533daff 1378
1379
1380=head1 UPDATING THE VIEW
1381
a8f4e284 1382Let's add a new column to our book list page that takes advantage of the
1383relationship information we manually added to our schema files in the
1384previous section. Edit C<root/src/books/list.tt2> and replace the
1385"empty" table cell "<td></td>" with the following:
3533daff 1386
acbd7bdd 1387 ...
3533daff 1388 <td>
fce83e5f 1389 [% # NOTE: See Chapter 4 for a better way to do this! -%]
3533daff 1390 [% # First initialize a TT variable to hold a list. Then use a TT FOREACH -%]
1391 [% # loop in 'side effect notation' to load just the last names of the -%]
6d97b973 1392 [% # authors into the list. Note that the 'push' TT vmethod doesn't return -%]
3533daff 1393 [% # a value, so nothing will be printed here. But, if you have something -%]
6d97b973 1394 [% # in TT that does return a value and you don't want it printed, you -%]
1395 [% # 1) assign it to a bogus value, or -%]
1396 [% # 2) use the CALL keyword to call it and discard the return value. -%]
3533daff 1397 [% tt_authors = [ ];
1398 tt_authors.push(author.last_name) FOREACH author = book.authors %]
1399 [% # Now use a TT 'virtual method' to display the author count in parens -%]
1400 [% # Note the use of the TT filter "| html" to escape dangerous characters -%]
1401 ([% tt_authors.size | html %])
1402 [% # Use another TT vmethod to join & print the names & comma separators -%]
1403 [% tt_authors.join(', ') | html %]
1404 </td>
acbd7bdd 1405 ...
3533daff 1406
a8f4e284 1407B<IMPORTANT NOTE:> Again, you should keep as much "logic code" as
1408possible out of your views. This kind of logic belongs in your model
1409(the same goes for controllers -- keep them as "thin" as possible and
1410push all of the "complicated code" out to your model objects). Avoid
1411code like you see in the previous example -- we are only using it here
1412to show some extra features in TT until we get to the more advanced
1413model features we will see in Chapter 4 (see
fce83e5f 1414L<Catalyst::Manual::Tutorial::04_BasicCRUD/EXPLORING THE POWER OF DBIC>).
1415
a8f4e284 1416Then hit "Reload" in your browser (note that you don't need to reload
1417the development server or use the C<-r> option when updating TT
1418templates) and you should now see the number of authors each book has
1419along with a comma-separated list of the authors' last names. (If you
1420didn't leave the development server running from the previous step, you
1421will obviously need to start it before you can refresh your browser
1422window.)
1390ef0e 1423
1424If you are still running the development server with C<DBIC_TRACE>
1425enabled, you should also now see five more C<SELECT> statements in the
1426debug output (one for each book as the authors are being retrieved by
a46b474e 1427DBIx::Class):
3533daff 1428
fce83e5f 1429 SELECT me.id, me.title, me.rating FROM book me:
3b1fa91b 1430 SELECT author.id, author.first_name, author.last_name FROM book_author me
fce83e5f 1431 JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '1'
3b1fa91b 1432 SELECT author.id, author.first_name, author.last_name FROM book_author me
fce83e5f 1433 JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '2'
3b1fa91b 1434 SELECT author.id, author.first_name, author.last_name FROM book_author me
fce83e5f 1435 JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '3'
3b1fa91b 1436 SELECT author.id, author.first_name, author.last_name FROM book_author me
fce83e5f 1437 JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '4'
3b1fa91b 1438 SELECT author.id, author.first_name, author.last_name FROM book_author me
fce83e5f 1439 JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '5'
c2dfb562 1440
a8f4e284 1441Also note in C<root/src/books/list.tt2> that we are using "| html", a
1442type of TT filter, to escape characters such as E<lt> and E<gt> to &lt;
1443and &gt; and avoid various types of dangerous hacks against your
1444application. In a real application, you would probably want to put "|
1445html" at the end of every field where a user has control over the
1446information that can appear in that field (and can therefore inject
1447markup or code if you don't "neutralize" those fields). In addition to
1448"| html", Template Toolkit has a variety of other useful filters that
1449can found in the documentation for
2217b252 1450L<Template::Filters>.
3533daff 1451
1452
1390ef0e 1453=head1 RUNNING THE APPLICATION FROM THE COMMAND LINE
1454
a8f4e284 1455In some situations, it can be useful to run your application and display
1456a page without using a browser. Catalyst lets you do this using the
1457C<scripts/myapp_test.pl> script. Just supply the URL you wish to
1458display and it will run that request through the normal controller
1459dispatch logic and use the appropriate view to render the output
1460(obviously, complex pages may dump a lot of text to your terminal
1461window). For example, if you type:
1390ef0e 1462
1463 $ script/myapp_test.pl "/books/list"
1464
1465You should get the same text as if you visited
1466L<http://localhost:3000/books/list> with the normal development server
1467and asked your browser to view the page source.
3533daff 1468
1390ef0e 1469
1470=head1 OPTIONAL INFORMATION
1471
4b4d3884 1472B<NOTE: The rest of this chapter of the tutorial is optional. You can
3ab6187c 1473skip to Chapter 4, L<Basic CRUD|Catalyst::Manual::Tutorial::04_BasicCRUD>,
3533daff 1474if you wish.>
1475
acbd7bdd 1476
8a472b34 1477=head2 Using 'RenderView' for the Default View
1390ef0e 1478
1479Once your controller logic has processed the request from a user, it
1480forwards processing to your view in order to generate the appropriate
3533daff 1481response output. Catalyst uses
2217b252 1482L<Catalyst::Action::RenderView> by default
a8f4e284 1483to automatically perform this operation. If you look in
1484C<lib/MyApp/Controller/Root.pm>, you should see the empty definition for
1485the C<sub end> method:
3533daff 1486
1487 sub end : ActionClass('RenderView') {}
1488
1390ef0e 1489The following bullet points provide a quick overview of the
3533daff 1490C<RenderView> process:
1491
1492=over 4
1493
1494=item *
1495
1496C<Root.pm> is designed to hold application-wide logic.
1497
1498=item *
1499
1390ef0e 1500At the end of a given user request, Catalyst will call the most specific
1501C<end> method that's appropriate. For example, if the controller for a
1502request has an C<end> method defined, it will be called. However, if
1503the controller does not define a controller-specific C<end> method, the
3533daff 1504"global" C<end> method in C<Root.pm> will be called.
1505
1506=item *
1507
1508Because the definition includes an C<ActionClass> attribute, the
2217b252 1509L<Catalyst::Action::RenderView> logic will
a8f4e284 1510be executed B<after> any code inside the definition of C<sub end> is
2217b252 1511run. See L<Catalyst::Manual::Actions> for
a8f4e284 1512more information on C<ActionClass>.
3533daff 1513
1514=item *
1515
1390ef0e 1516Because C<sub end> is empty, this effectively just runs the default
1517logic in C<RenderView>. However, you can easily extend the
1518C<RenderView> logic by adding your own code inside the empty method body
1519(C<{}>) created by the Catalyst Helpers when we first ran the
1520C<catalyst.pl> to initialize our application. See
2217b252 1521L<Catalyst::Action::RenderView> for more
4d63a0d5 1522detailed information on how to extend C<RenderView> in C<sub end>.
3533daff 1523
1524=back
1525
1526
fce83e5f 1527=head2 RenderView's "dump_info" Feature
1528
a8f4e284 1529One of the nice features of C<RenderView> is that it automatically
1530allows you to add C<dump_info=1> to the end of any URL for your
1531application and it will force the display of the "exception dump" screen
1532to the client browser. You can try this out by pointing your browser to
1533this URL:
fce83e5f 1534
1535 http://localhost:3000/books/list?dump_info=1
1536
1537You should get a page with the following message at the top:
1538
1539 Caught exception in MyApp::Controller::Root->end "Forced debug -
1540 Scrubbed output at /usr/share/perl5/Catalyst/Action/RenderView.pm line 46."
1541
a8f4e284 1542Along with a summary of your application's state at the end of the
1543processing for that request. The "Stash" section should show a
1544summarized version of the DBIC book model objects. If desired, you can
1545adjust the summarization logic (called "scrubbing" logic) -- see
2217b252 1546L<Catalyst::Action::RenderView> for
fce83e5f 1547details.
1548
a8f4e284 1549Note that you shouldn't need to worry about "normal clients" using this
1550technique to "reverse engineer" your application -- C<RenderView> only
1551supports the C<dump_info=1> feature when your application is running in
1552C<-Debug> mode (something you won't do once you have your application
1553deployed in production).
fce83e5f 1554
1555
3533daff 1556=head2 Using The Default Template Name
1557
1390ef0e 1558By default, C<Catalyst::View::TT> will look for a template that uses the
1559same name as your controller action, allowing you to save the step of
1560manually specifying the template name in each action. For example, this
a8f4e284 1561would allow us to remove the C<$c-E<gt>stash-E<gt>{template} =
1562'books/list.tt2';> line of our C<list> action in the Books controller.
1563Open C<lib/MyApp/Controller/Books.pm> in your editor and comment out
1564this line to match the following (only the
1565C<$c-E<gt>stash-E<gt>{template}> line has changed):
3533daff 1566
1567 =head2 list
1568
1569 Fetch all book objects and pass to books/list.tt2 in stash to be displayed
1570
1571 =cut
1572
ddfbd850 1573 sub list :Local {
3533daff 1574 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
1575 # 'Context' that's used to 'glue together' the various components
1576 # that make up the application
1577 my ($self, $c) = @_;
1578
1579 # Retrieve all of the book records as book model objects and store in the
1580 # stash where they can be accessed by the TT template
0ed3df53 1581 $c->stash(books => [$c->model('DB::Book')->all]);
3533daff 1582
1583 # Set the TT template to use. You will almost always want to do this
1584 # in your action methods (actions methods respond to user input in
1585 # your controllers).
61cb69fd 1586 #$c->stash(template => 'books/list.tt2');
3533daff 1587 }
1588
3533daff 1589
6961c906 1590You should now be able to access the L<http://localhost:3000/books/list>
1591URL as before.
3533daff 1592
a8f4e284 1593B<NOTE:> Please note that if you use the default template technique, you
1594will B<not> be able to use either the C<$c-E<gt>forward> or the
1595C<$c-E<gt>detach> mechanisms (these are discussed in Chapter 2 and
4b4d3884 1596Chapter 9 of the Tutorial).
3533daff 1597
3b1fa91b 1598B<IMPORTANT:> Make sure that you do NOT skip the following section
1599before continuing to the next chapter 4 Basic CRUD.
3533daff 1600
fce83e5f 1601
4d63a0d5 1602=head2 Return To A Manually Specified Template
3533daff 1603
1604In order to be able to use C<$c-E<gt>forward> and C<$c-E<gt>detach>
a8f4e284 1605later in the tutorial, you should remove the comment from the statement
1606in C<sub list> in C<lib/MyApp/Controller/Books.pm>:
3533daff 1607
0ed3df53 1608 $c->stash(template => 'books/list.tt2');
3533daff 1609
a8f4e284 1610Then delete the C<TEMPLATE_EXTENSION> line in C<lib/MyApp/View/HTML.pm>.
3533daff 1611
a8f4e284 1612Check the L<http://localhost:3000/books/list> URL in your browser. It
1613should look the same manner as with earlier sections.
3533daff 1614
1615
1616=head1 AUTHOR
1617
1618Kennedy Clark, C<hkclark@gmail.com>
1619
53243324 1620Feel free to contact the author for any errors or suggestions, but the
1621best way to report issues is via the CPAN RT Bug system at
1622<https://rt.cpan.org/Public/Dist/Display.html?Name=Catalyst-Manual>.
1623
1624The most recent version of the Catalyst Tutorial can be found at
59884771 1625L<http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Manual/5.80/trunk/lib/Catalyst/Manual/Tutorial/>.
3533daff 1626
ec3ef4ad 1627Copyright 2006-2010, Kennedy Clark, under the
1628Creative Commons Attribution Share-Alike License Version 3.0
8482d557 1629(L<http://creativecommons.org/licenses/by-sa/3.0/us/>).