1Catalyst::Manual::TutorUisaelr:C:Ca0ot3na_tlMryoisrbteu:Ct:aeMtdaanlPuyeasrltl:B:aDTsouictcuosmr(ei3na)tla:t:i0o3n_MoreCatalystBasics(3)
2
3
4

NAME

6       Catalyst::Manual::Tutorial::03_MoreCatalystBasics - Catalyst Tutorial -
7       Chapter 3: More Catalyst Application Development Basics
8

OVERVIEW

10       This is Chapter 3 of 10 for the Catalyst tutorial.
11
12       Tutorial Overview
13
14       1.  Introduction
15
16       2.  Catalyst Basics
17
18       3.  03_More Catalyst Basics
19
20       4.  Basic CRUD
21
22       5.  Authentication
23
24       6.  Authorization
25
26       7.  Debugging
27
28       8.  Testing
29
30       9.  Advanced CRUD
31
32       10. Appendices
33

DESCRIPTION

35       This chapter of the tutorial builds on the work done in Chapter 2 to
36       explore some features that are more typical of "real world" web
37       applications. From this chapter of the tutorial onward, we will be
38       building a simple book database application.  Although the application
39       will be too limited to be of use to anyone, it should provide a basic
40       environment where we can explore a variety of features used in
41       virtually all web applications.
42
43       Source code for the tutorial in included in the /home/catalyst/Final
44       directory of the Tutorial Virtual machine (one subdirectory per
45       chapter).  There are also instructions for downloading the code in
46       Catalyst::Manual::Tutorial::01_Intro.
47
48       Please take a look at "STARTING WITH THE TUTORIAL VIRTUAL MACHINE" in
49       Catalyst::Manual::Tutorial::01_Intro before doing the rest of this
50       tutorial.  Although the tutorial should work correctly under most any
51       recent version of Perl running on any operating system, the tutorial
52       has been written using the virtual machine that is available for
53       download.  The entire tutorial has been tested to be sure it runs
54       correctly in this environment, so it is the most trouble-free way to
55       get started with Catalyst.
56

CREATE A NEW APPLICATION

58       The remainder of the tutorial will build an application called "MyApp".
59       First use the Catalyst catalyst.pl script to initialize the framework
60       for the "MyApp" application (make sure you aren't still inside the
61       directory of the "Hello" application from the previous chapter of the
62       tutorial or in a directory that already has a "MyApp" subdirectory):
63
64           $ catalyst.pl MyApp
65           created "MyApp"
66           created "MyApp/script"
67           created "MyApp/lib"
68           created "MyApp/root"
69           ...
70           created "MyApp/script/myapp_create.pl"
71           Change to application directory and Run "perl Makefile.PL" to make sure your install is complete
72
73       And change the "MyApp" directory the helper created:
74
75           $ cd MyApp
76
77       This creates a similar skeletal structure to what we saw in Chapter 2
78       of the tutorial, except with "MyApp" and "myapp" substituted for
79       "Hello" and "hello".  (As noted in Chapter 2, omit the ".pl" from the
80       command if you are using Strawberry Perl.)
81

EDIT THE LIST OF CATALYST PLUGINS

83       One of the greatest benefits of Catalyst is that it has such a large
84       library of base classes and plugins available that you can use to
85       easily add functionality to your application. Plugins are used to
86       seamlessly integrate existing Perl modules into the overall Catalyst
87       framework. In general, they do this by adding additional methods to the
88       "context" object (generally written as $c) that Catalyst passes to
89       every component throughout the framework.
90
91       Take a look at the file lib/MyApp.pm that the helper created above.  By
92       default, Catalyst enables three plugins/flags:
93
94       •   "-Debug" Flag
95
96           Enables the Catalyst debug output you saw when we started the
97           script/myapp_server.pl development server earlier.  You can remove
98           this item when you place your application into production.
99
100           To be technically correct, it turns out that "-Debug" is not a
101           plugin, but a flag.  Although most of the items specified on the
102           "use Catalyst" line of your application class will be plugins,
103           Catalyst supports a limited number of flag options (of these,
104           "-Debug" is the most common).  See the documentation for
105           Catalyst.pm to get details on other flags (currently "-Engine",
106           "-Home", "-Log", and "-Stats").
107
108           If you prefer, there are several other ways to enable debug output:
109
110           •   the "$c->debug" method on the $c Catalyst context object
111
112           •   the "-d" option on the script/myapp_server.pl script
113
114           •   the "CATALYST_DEBUG=1" environment variable (or
115               "CATALYST_DEBUG=0" to temporarily disable debug output)
116
117           TIP: Depending on your needs, it can be helpful to permanently
118           remove "-Debug" from "lib/MyApp.pm" and then use the "-d" option to
119           script/myapp_server.pl to re-enable it when needed.  We will not be
120           using that approach in the tutorial, but feel free to make use of
121           it in your own projects.
122
123       •   Catalyst::Plugin::ConfigLoader
124
125           "ConfigLoader" provides an automatic way to load configurable
126           parameters for your application from a central Config::General file
127           (versus having the values hard-coded inside your Perl modules).
128           Config::General uses syntax very similar to Apache configuration
129           files.  We will see how to use this feature of Catalyst during the
130           authentication and authorization sections (Chapter 5 and Chapter
131           6).
132
133           IMPORTANT NOTE: If you are using a version of Catalyst::Devel prior
134           to version 1.06, be aware that Catalyst changed the default format
135           from YAML to the more straightforward Config::General style.  This
136           tutorial uses the newer "myapp.conf" file for Config::General.
137           However, Catalyst supports both formats and will automatically use
138           either myapp.conf or myapp.yml (or any other format supported by
139           Catalyst::Plugin::ConfigLoader and Config::Any).  If you are using
140           a version of Catalyst::Devel prior to 1.06, you can convert to the
141           newer format by simply creating the myapp.conf file manually and
142           deleting myapp.yml.  The default contents of the myapp.conf you
143           create should only consist of one line:
144
145               name MyApp
146
147           TIP: This script can be useful for converting between configuration
148           formats:
149
150               perl -Ilib -e 'use MyApp; use Config::General;
151                   Config::General->new->save_file("myapp.conf", MyApp->config);'
152
153       •   Catalyst::Plugin::Static::Simple
154
155           "Static::Simple" provides an easy way to serve static content, such
156           as images and CSS files, from the development server.
157
158       For our application, we want to add one new plugin to the mix.  To do
159       this, edit lib/MyApp.pm (this file is generally referred to as your
160       application class) and delete the lines with:
161
162           use Catalyst qw/
163               -Debug
164               ConfigLoader
165               Static::Simple
166           /;
167
168       Then replace it with:
169
170           # Load plugins
171           use Catalyst qw/
172               -Debug
173               ConfigLoader
174               Static::Simple
175
176               StackTrace
177           /;
178
179       Note: Recent versions of Catalyst::Devel have used a variety of
180       techniques to load these plugins/flags.  For example, you might see the
181       following:
182
183           __PACKAGE__->setup(qw/-Debug ConfigLoader Static::Simple/);
184
185       Don't let these variations confuse you -- they all accomplish the same
186       result.
187
188       This tells Catalyst to start using one additional plugin,
189       Catalyst::Plugin::StackTrace, to add a stack trace near the top of the
190       standard Catalyst "debug screen" (the screen Catalyst sends to your
191       browser when an error occurs). Be aware that StackTrace output appears
192       in your browser, not in the console window from which you're running
193       your application, which is where logging output usually goes.
194
195       Make sure when adding new plugins you also include them as a new
196       dependency within the Makefile.PL file. For example, after adding the
197       StackTrace plugin the Makefile.PL should include the following line:
198
199           requires 'Catalyst::Plugin::StackTrace';
200
201       Notes:
202
203       •   "__PACKAGE__" is just a shorthand way of referencing the name of
204           the package where it is used.  Therefore, in MyApp.pm,
205           "__PACKAGE__" is equivalent to "MyApp".
206
207       •   You will want to disable StackTrace before you put your application
208           into production, but it can be helpful during development.
209
210       •   When specifying plugins, you can omit "Catalyst::Plugin::" from the
211           name.  Additionally, you can spread the plugin names across
212           multiple lines as shown here or place them all on one line.
213
214       •   If you want to see what the StackTrace error screen looks like,
215           edit lib/MyApp/Controller/Root.pm and put a "die "Oops";" command
216           in the "sub index :Path :Args(0)" method.  Then start the
217           development server and open "http://localhost:3000/" in your
218           browser.  You should get a screen that starts with "Caught
219           exception in MyApp::Controller::Root->index" with sections showing
220           a stacktrace, information about the Request and Response objects,
221           the stash (something we will learn about soon), and the
222           applications configuration.  Just don't forget to remove the die
223           before you continue the tutorial!  :-)
224

CREATE A CATALYST CONTROLLER

226       As discussed earlier, controllers are where you write methods that
227       interact with user input.  Typically, controller methods respond to
228       "GET" and "POST" requests from the user's web browser.
229
230       Use the Catalyst "create" script to add a controller for book-related
231       actions:
232
233           $ script/myapp_create.pl controller Books
234            exists "/home/catalyst/MyApp/script/../lib/MyApp/Controller"
235            exists "/home/catalyst/MyApp/script/../t"
236           created "/home/catalyst/MyApp/script/../lib/MyApp/Controller/Books.pm"
237           created "/home/catalyst/MyApp/script/../t/controller_Books.t"
238
239       Then edit lib/MyApp/Controller/Books.pm (as discussed in Chapter 2 of
240       the Tutorial, Catalyst has a separate directory under lib/MyApp for
241       each of the three parts of MVC: "Model", "View" and "Controller") and
242       add the following method to the controller:
243
244           =head2 list
245
246           Fetch all book objects and pass to books/list.tt2 in stash to be displayed
247
248           =cut
249
250           sub list :Local {
251               # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
252               # 'Context' that's used to 'glue together' the various components
253               # that make up the application
254               my ($self, $c) = @_;
255
256               # Retrieve all of the book records as book model objects and store in the
257               # stash where they can be accessed by the TT template
258               # $c->stash(books => [$c->model('DB::Book')->all]);
259               # But, for now, use this code until we create the model later
260               $c->stash(books => '');
261
262               # Set the TT template to use.  You will almost always want to do this
263               # in your action methods (action methods respond to user input in
264               # your controllers).
265               $c->stash(template => 'books/list.tt2');
266           }
267
268       TIP: See Appendix 1 for tips on removing the leading spaces when
269       cutting and pasting example code from POD-based documents.
270
271       Programmers experienced with object-oriented Perl should recognize
272       $self as a reference to the object where this method was called.  On
273       the other hand, $c will be new to many Perl programmers who have not
274       used Catalyst before.  This is the "Catalyst Context object", and it is
275       automatically passed as the second argument to all Catalyst action
276       methods.  It is used to pass information between components and provide
277       access to Catalyst and plugin functionality.
278
279       Catalyst Controller actions are regular Perl methods, but they make use
280       of attributes (the "":Local"" next to the ""sub list"" in the code
281       above) to provide additional information to the Catalyst dispatcher
282       logic (note that there can be an optional space between the colon and
283       the attribute name; you will see attributes written both ways).  Most
284       Catalyst Controllers use one of five action types:
285
286:Private -- Use ":Private" for methods that you want to make into
287           an action, but you do not want Catalyst to directly expose the
288           method to your users.  Catalyst will not map ":Private" methods to
289           a URI.  Use them for various sorts of "special" methods (the
290           "begin", "auto", etc.  discussed below) or for methods you want to
291           be able to "forward" or "detach" to.  (If the method is a "plain
292           old method" that you don't want to be an action at all, then just
293           define the method without any attribute -- you can call it in your
294           code, but the Catalyst dispatcher will ignore it.  You will also
295           have to manually include $c if you want access to the context
296           object in the method vs. having Catalyst automatically include $c
297           in the argument list for you if it's a full-fledged action.)
298
299           There are five types of "special" built-in ":Private" actions:
300           "begin", "end", "default", "index", and "auto".
301
302           •   With "begin", "end", "default", "index" private actions, only
303               the most specific action of each type will be called.  For
304               example, if you define a "begin" action in your controller it
305               will override a "begin" action in your application/root
306               controller -- only the action in your controller will be
307               called.
308
309           •   Unlike the other actions where only a single method is called
310               for each request, every auto action along the chain of
311               namespaces will be called.  Each "auto" action will be called
312               from the application/root controller down through the most
313               specific class.
314
315:Path -- ":Path" actions let you map a method to an explicit URI
316           path.  For example, "":Path('list')"" in
317           lib/MyApp/Controller/Books.pm would match on the URL
318           "http://localhost:3000/books/list", but "":Path('/list')"" would
319           match on "http://localhost:3000/list" (because of the leading
320           slash).  You can use ":Args()" to specify how many arguments an
321           action should accept.  See "Action-types" in
322           Catalyst::Manual::Intro for more information and examples.
323
324:Local -- ":Local" is merely a shorthand for
325           "":Path('_name_of_method_')"".  For example, these are equivalent:
326           ""sub create_book :Local {...}"" and ""sub create_book
327           :Path('create_book') {...}"".
328
329:Global -- ":Global" is merely a shorthand for
330           "":Path('/_name_of_method_')"".  For example, these are equivalent:
331           ""sub create_book :Global {...}"" and ""sub create_book
332           :Path('/create_book') {...}"".
333
334:Chained -- Newer Catalyst applications tend to use the Chained
335           dispatch form of action types because of its power and flexibility.
336           It allows a series of controller methods to be automatically
337           dispatched when servicing a single user request.  See
338           Catalyst::Manual::Tutorial::04_BasicCRUD and
339           Catalyst::DispatchType::Chained for more information on chained
340           actions.
341
342       You should refer to "Action-types" in Catalyst::Manual::Intro for
343       additional information and for coverage of some lesser-used action
344       types not discussed here ("Regex" and "LocalRegex").
345

CATALYST VIEWS

347       As mentioned in Chapter 2 of the tutorial, views are where you render
348       output, typically for display in the user's web browser (but can
349       generate other types of output such as PDF or JSON).  The code in
350       lib/MyApp/View selects the type of view to use, with the actual
351       rendering template found in the "root" directory.  As with virtually
352       every aspect of Catalyst, options abound when it comes to the specific
353       view technology you adopt inside your application. However, most
354       Catalyst applications use the Template Toolkit, known as TT (for more
355       information on TT, see <http://www.template-toolkit.org>). Other
356       somewhat popular view technologies include Mason
357       (<http://www.masonhq.com> and
358       <https://masonbook.houseabsolute.com/book/>) and HTML::Template.
359
360   Create a Catalyst View
361       When using TT for the Catalyst view, the main helper script is
362       Catalyst::Helper::View::TT.  You may also come across references to
363       Catalyst::Helper::View::TTSite, but its use is now deprecated.
364
365       For our book application, enter the following command to enable the
366       "TT" style of view rendering:
367
368           $ script/myapp_create.pl view HTML TT
369            exists "/home/catalyst/MyApp/script/../lib/MyApp/View"
370            exists "/home/catalyst/MyApp/script/../t"
371            created "/home/catalyst/MyApp/script/../lib/MyApp/View/HTML.pm"
372            created "/home/catalyst/MyApp/script/../t/view_HTML.t"
373
374       This creates a view called "HTML" (the first argument) in a file called
375       "HTML.pm" that uses Catalyst::View::TT (the second argument) as the
376       "rendering engine".
377
378       It is now up to you to decide how you want to structure your view
379       layout.  For the tutorial, we will start with a very simple TT template
380       to initially demonstrate the concepts, but quickly migrate to a more
381       typical "wrapper page" type of configuration (where the "wrapper"
382       controls the overall "look and feel" of your site from a single file or
383       set of files).
384
385       Edit lib/MyApp/View/HTML.pm and you should see something similar to the
386       following:
387
388           __PACKAGE__->config(
389               TEMPLATE_EXTENSION => '.tt',
390               render_die => 1,
391           );
392
393       And update it to match:
394
395           __PACKAGE__->config(
396               # Change default TT extension
397               TEMPLATE_EXTENSION => '.tt2',
398               render_die => 1,
399           );
400
401       This changes the default extension for Template Toolkit from '.tt' to
402       '.tt2'.
403
404       You can also configure components in your application class. For
405       example, Edit lib/MyApp.pm and you should see the default configuration
406       above the call to "_PACKAGE__->setup" (your defaults could be different
407       depending on the version of Catalyst you are using):
408
409           __PACKAGE__->config(
410               name => 'MyApp',
411               # Disable deprecated behavior needed by old applications
412               disable_component_resolution_regex_fallback => 1,
413           );
414
415       Change this to match the following (insert a new "__PACKAGE__->config"
416       below the existing statement):
417
418           __PACKAGE__->config(
419               name => 'MyApp',
420               # Disable deprecated behavior needed by old applications
421               disable_component_resolution_regex_fallback => 1,
422           );
423           __PACKAGE__->config(
424               # Configure the view
425               'View::HTML' => {
426                   #Set the location for TT files
427                   INCLUDE_PATH => [
428                       __PACKAGE__->path_to( 'root', 'src' ),
429                   ],
430               },
431           );
432
433       This changes the base directory for your template files from "root" to
434       root/src.
435
436       Please stick with the settings above for the duration of the tutorial,
437       but feel free to use whatever options you desire in your applications
438       (as with most things in Perl, there's more than one way to do it...).
439
440       Note: We will use root/src as the base directory for our template
441       files, with a full naming convention of
442       root/src/_controller_name_/_action_name_.tt2.  Another popular option
443       is to use root/ as the base (with a full filename pattern of
444       root/_controller_name_/_action_name_.tt2).
445
446   Create a TT Template Page
447       First create a directory for book-related TT templates:
448
449           $ mkdir -p root/src/books
450
451       Then create root/src/books/list.tt2 in your editor and enter:
452
453           [% # This is a TT comment. -%]
454
455           [%- # Provide a title -%]
456           [% META title = 'Book List' -%]
457
458           [% # Note That the '-' at the beginning or end of TT code  -%]
459           [% # "chomps" the whitespace/newline at that end of the    -%]
460           [% # output (use View Source in browser to see the effect) -%]
461
462           [% # Some basic HTML with a loop to display books -%]
463           <table>
464           <tr><th>Title</th><th>Rating</th><th>Author(s)</th></tr>
465           [% # Display each book in a table row %]
466           [% FOREACH book IN books -%]
467             <tr>
468               <td>[% book.title %]</td>
469               <td>[% book.rating %]</td>
470               <td></td>
471             </tr>
472           [% END -%]
473           </table>
474
475       As indicated by the inline comments above, the "META title" line uses
476       TT's META feature to provide a title to the "wrapper" that we will
477       create later (and essentially does nothing at the moment). Meanwhile,
478       the "FOREACH" loop iterates through each "book" model object and prints
479       the "title" and "rating" fields.
480
481       The "[%" and "%]" tags are used to delimit Template Toolkit code.  TT
482       supports a wide variety of directives for "calling" other files,
483       looping, conditional logic, etc.  In general, TT simplifies the usual
484       range of Perl operators down to the single dot (".") operator.  This
485       applies to operations as diverse as method calls, hash lookups, and
486       list index values (see Template::Manual::Variables for details and
487       examples).  In addition to the usual Template::Toolkit module Pod
488       documentation, you can access the TT manual at Template::Manual.
489
490       TIP: While you can build all sorts of complex logic into your TT
491       templates, you should in general keep the "code" part of your templates
492       as simple as possible.  If you need more complex logic, create helper
493       methods in your model that abstract out a set of code into a single
494       call from your TT template.  (Note that the same is true of your
495       controller logic as well -- complex sections of code in your
496       controllers should often be pulled out and placed into your model
497       objects.)  In Chapter 4 of the tutorial we will explore some extremely
498       helpful and powerful features of DBIx::Class that allow you to pull
499       code out of your views and controllers and place it where it rightfully
500       belongs in a model class.
501
502   Test Run The Application
503       To test your work so far, first start the development server:
504
505           $ script/myapp_server.pl -r
506
507       Then point your browser to <http://localhost:3000> and you should still
508       get the Catalyst welcome page.  Next, change the URL in your browser to
509       <http://localhost:3000/books/list>.  If you have everything working so
510       far, you should see a web page that displays nothing other than our
511       column headers for "Title", "Rating", and "Author(s)" -- we will not
512       see any books until we get the database and model working below.
513
514       If you run into problems getting your application to run correctly, it
515       might be helpful to refer to some of the debugging techniques covered
516       in the Debugging chapter of the tutorial.
517

CREATE A SQLITE DATABASE

519       In this step, we make a text file with the required SQL commands to
520       create a database table and load some sample data.  We will use SQLite
521       (<https://www.sqlite.org>), a popular database that is lightweight and
522       easy to use. Be sure to get at least version 3. Open myapp01.sql in
523       your editor and enter:
524
525           --
526           -- Create a very simple database to hold book and author information
527           --
528           PRAGMA foreign_keys = ON;
529           CREATE TABLE book (
530                   id          INTEGER PRIMARY KEY,
531                   title       TEXT ,
532                   rating      INTEGER
533           );
534           -- 'book_author' is a many-to-many join table between books & authors
535           CREATE TABLE book_author (
536                   book_id     INTEGER REFERENCES book(id) ON DELETE CASCADE ON UPDATE CASCADE,
537                   author_id   INTEGER REFERENCES author(id) ON DELETE CASCADE ON UPDATE CASCADE,
538                   PRIMARY KEY (book_id, author_id)
539           );
540           CREATE TABLE author (
541                   id          INTEGER PRIMARY KEY,
542                   first_name  TEXT,
543                   last_name   TEXT
544           );
545           ---
546           --- Load some sample data
547           ---
548           INSERT INTO book VALUES (1, 'CCSP SNRS Exam Certification Guide', 5);
549           INSERT INTO book VALUES (2, 'TCP/IP Illustrated, Volume 1', 5);
550           INSERT INTO book VALUES (3, 'Internetworking with TCP/IP Vol.1', 4);
551           INSERT INTO book VALUES (4, 'Perl Cookbook', 5);
552           INSERT INTO book VALUES (5, 'Designing with Web Standards', 5);
553           INSERT INTO author VALUES (1, 'Greg', 'Bastien');
554           INSERT INTO author VALUES (2, 'Sara', 'Nasseh');
555           INSERT INTO author VALUES (3, 'Christian', 'Degu');
556           INSERT INTO author VALUES (4, 'Richard', 'Stevens');
557           INSERT INTO author VALUES (5, 'Douglas', 'Comer');
558           INSERT INTO author VALUES (6, 'Tom', 'Christiansen');
559           INSERT INTO author VALUES (7, 'Nathan', 'Torkington');
560           INSERT INTO author VALUES (8, 'Jeffrey', 'Zeldman');
561           INSERT INTO book_author VALUES (1, 1);
562           INSERT INTO book_author VALUES (1, 2);
563           INSERT INTO book_author VALUES (1, 3);
564           INSERT INTO book_author VALUES (2, 4);
565           INSERT INTO book_author VALUES (3, 5);
566           INSERT INTO book_author VALUES (4, 6);
567           INSERT INTO book_author VALUES (4, 7);
568           INSERT INTO book_author VALUES (5, 8);
569
570       Then use the following command to build a myapp.db SQLite database:
571
572           $ sqlite3 myapp.db < myapp01.sql
573
574       If you need to create the database more than once, you probably want to
575       issue the "rm myapp.db" command to delete the database before you use
576       the "sqlite3 myapp.db < myapp01.sql" command.
577
578       Once the myapp.db database file has been created and initialized, you
579       can use the SQLite command line environment to do a quick dump of the
580       database contents:
581
582           $ sqlite3 myapp.db
583           SQLite version 3.7.3
584           Enter ".help" for instructions
585           Enter SQL statements terminated with a ";"
586           sqlite> select * from book;
587           1|CCSP SNRS Exam Certification Guide|5
588           2|TCP/IP Illustrated, Volume 1|5
589           3|Internetworking with TCP/IP Vol.1|4
590           4|Perl Cookbook|5
591           5|Designing with Web Standards|5
592           sqlite> .q
593           $
594
595       Or:
596
597           $ sqlite3 myapp.db "select * from book"
598           1|CCSP SNRS Exam Certification Guide|5
599           2|TCP/IP Illustrated, Volume 1|5
600           3|Internetworking with TCP/IP Vol.1|4
601           4|Perl Cookbook|5
602           5|Designing with Web Standards|5
603
604       As with most other SQL tools, if you are using the full "interactive"
605       environment you need to terminate your SQL commands with a ";" (it's
606       not required if you do a single SQL statement on the command line).
607       Use ".q" to exit from SQLite from the SQLite interactive mode and
608       return to your OS command prompt.
609
610       Please note that here we have chosen to use 'singular' table names.
611       This is because the default inflection code for older versions of
612       DBIx::Class::Schema::Loader does NOT handle plurals. There has been
613       much philosophical discussion on whether table names should be plural
614       or singular.  There is no one correct answer, as long as one makes a
615       choice and remains consistent with it. If you prefer plural table names
616       (e.g.  you think that they are easier to read) then see the
617       documentation in "naming" in DBIx::Class::Schema::Loader::Base (version
618       0.05 or greater).
619
620       For using other databases, such as PostgreSQL or MySQL, see Appendix 2.
621

DATABASE ACCESS WITH DBIx::Class

623       Catalyst can be used with virtually any form of datastore available via
624       Perl.  For example, Catalyst::Model::DBI can be used to access
625       databases through the traditional Perl DBI interface or you can use a
626       model to access files of any type on the filesystem.  However, most
627       Catalyst applications use some form of object-relational mapping (ORM)
628       technology to create objects associated with tables in a relational
629       database, and Matt Trout's DBIx::Class (abbreviated as "DBIC") is the
630       usual choice (this tutorial will use DBIx::Class).
631
632       Although DBIx::Class has included support for a "create=dynamic" mode
633       to automatically read the database structure every time the application
634       starts, its use is no longer recommended.  While it can make for
635       "flashy" demos, the use of the "create=static" mode we use below can be
636       implemented just as quickly and provides many advantages (such as the
637       ability to add your own methods to the overall DBIC framework, a
638       technique that we see in Chapter 4).
639
640   Create Static DBIx::Class Schema Files
641       Note: If you are not following along in the Tutorial Virtual Machine,
642       please be sure that you have version 1.27 or higher of DBD::SQLite and
643       version 0.39 or higher of Catalyst::Model::DBIC::Schema.  (The Tutorial
644       VM already has versions that are known to work.)  You can get your
645       currently installed version numbers with the following commands.
646
647           $ perl -MCatalyst::Model::DBIC::Schema\ 999
648           $ perl -MDBD::SQLite\ 999
649
650       Before you continue, make sure your myapp.db database file is in the
651       application's topmost directory. Now use the model helper with the
652       "create=static" option to read the database with
653       DBIx::Class::Schema::Loader and automatically build the required files
654       for us:
655
656           $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
657               create=static dbi:SQLite:myapp.db \
658               on_connect_do="PRAGMA foreign_keys = ON"
659            exists "/home/catalyst/MyApp/script/../lib/MyApp/Model"
660            exists "/home/catalyst/MyApp/script/../t"
661           Dumping manual schema for MyApp::Schema to directory /home/catalyst/MyApp/script/../lib ...
662           Schema dump completed.
663           created "/home/catalyst/MyApp/script/../lib/MyApp/Model/DB.pm"
664           created "/home/catalyst/MyApp/script/../t/model_DB.t"
665
666       Please note the '\' above.  Depending on your environment, you might be
667       able to cut and paste the text as shown or need to remove the '\'
668       character to that the command is all on a single line.
669
670       The script/myapp_create.pl command breaks down like this:
671
672       •   "DB" is the name of the model class to be created by the helper in
673           the lib/MyApp/Model directory.
674
675       •   "DBIC::Schema" is the type of the model to create.  This equates to
676           Catalyst::Model::DBIC::Schema, the standard way to use a DBIC-based
677           model inside of Catalyst.
678
679       •   "MyApp::Schema" is the name of the DBIC schema file written to
680           lib/MyApp/Schema.pm.
681
682       •   "create=static" causes DBIx::Class::Schema::Loader to load the
683           schema as it runs and then write that information out into
684           lib/MyApp/Schema.pm and files under the lib/MyApp/Schema directory.
685
686       •   "dbi:SQLite:myapp.db" is the standard DBI connect string for use
687           with SQLite.
688
689       •   And finally, the "on_connect_do" string requests that
690           DBIx::Class::Schema::Loader create foreign key relationships for us
691           (this is not needed for databases such as PostgreSQL and MySQL, but
692           is required for SQLite). If you take a look at
693           lib/MyApp/Model/DB.pm, you will see that the SQLite pragma is
694           propagated to the Model, so that SQLite's recent (and optional)
695           foreign key enforcement is enabled at the start of every database
696           connection.
697
698       If you look in the lib/MyApp/Schema.pm file, you will find that it only
699       contains a call to the "load_namespaces" method.  You will also find
700       that lib/MyApp contains a "Schema" subdirectory, which then has a
701       subdirectory called "Result".  This "Result" subdirectory then has
702       files named according to each of the tables in our simple database
703       (Author.pm, BookAuthor.pm, and Book.pm).  These three files are called
704       "Result Classes" (or "ResultSource Classes") in DBIx::Class
705       nomenclature. Although the Result Class files are named after tables in
706       our database, the classes correspond to the row-level data that is
707       returned by DBIC (more on this later, especially in "EXPLORING THE
708       POWER OF DBIC" in Catalyst::Manual::Tutorial::04_BasicCRUD).
709
710       The idea with the Result Source files created under
711       lib/MyApp/Schema/Result by the "create=static" option is to only edit
712       the files below the "# DO NOT MODIFY THIS OR ANYTHING ABOVE!"  warning.
713       If you place all of your changes below that point in the file, you can
714       regenerate the automatically created information at the top of each
715       file should your database structure get updated.
716
717       Also note the "flow" of the model information across the various files
718       and directories.  Catalyst will initially load the model from
719       lib/MyApp/Model/DB.pm.  This file contains a reference to
720       lib/MyApp/Schema.pm, so that file is loaded next.  Finally, the call to
721       "load_namespaces" in "Schema.pm" will load each of the "Result Class"
722       files from the lib/MyApp/Schema/Result subdirectory.  The final outcome
723       is that Catalyst will dynamically create three table-specific Catalyst
724       models every time the application starts (you can see these three model
725       files listed in the debug output generated when you launch the
726       application).
727
728       Additionally, the lib/MyApp/Schema.pm model can easily be loaded
729       outside of Catalyst, for example, in command-line utilities and/or cron
730       jobs. lib/MyApp/Model/DB.pm provides a very thin "bridge" between
731       Catalyst and this external database model.  Once you see how we can add
732       some powerful features to our DBIC model in Chapter 4, the elegance of
733       this approach will start to become more obvious.
734
735       NOTE: Older versions of Catalyst::Model::DBIC::Schema use the
736       deprecated DBIx::Class "load_classes" technique instead of the newer
737       "load_namespaces".  For new applications, please try to use
738       "load_namespaces" since it more easily supports a very useful DBIC
739       technique called "ResultSet Classes."  If you need to convert an
740       existing application from "load_classes" to "load_namespaces," you can
741       use this process to automate the migration, but first make sure you
742       have version 0.39 of Catalyst::Model::DBIC::Schema and
743       DBIx::Class::Schema::Loader version 0.05000 or later.
744
745           $ # Re-run the helper to upgrade for you
746           $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
747               create=static naming=current use_namespaces=1 \
748               dbi:SQLite:myapp.db \
749               on_connect_do="PRAGMA foreign_keys = ON"
750

ENABLE THE MODEL IN THE CONTROLLER

752       Open lib/MyApp/Controller/Books.pm and un-comment the model code we
753       left disabled earlier so that your version matches the following (un-
754       comment the line containing "[$c->model('DB::Book')->all]" and delete
755       the next 2 lines):
756
757           =head2 list
758
759           Fetch all book objects and pass to books/list.tt2 in stash to be displayed
760
761           =cut
762
763           sub list :Local {
764               # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
765               # 'Context' that's used to 'glue together' the various components
766               # that make up the application
767               my ($self, $c) = @_;
768
769               # Retrieve all of the book records as book model objects and store
770               # in the stash where they can be accessed by the TT template
771               $c->stash(books => [$c->model('DB::Book')->all]);
772
773               # Set the TT template to use.  You will almost always want to do this
774               # in your action methods (action methods respond to user input in
775               # your controllers).
776               $c->stash(template => 'books/list.tt2');
777           }
778
779       TIP: You may see the "$c->model('DB::Book')" un-commented above written
780       as "$c->model('DB')->resultset('Book')".  The two are equivalent.
781       Either way, "$c->model" returns a DBIx::Class::ResultSet which handles
782       queries against the database and iterating over the set of results that
783       is returned.
784
785       We are using the "->all" to fetch all of the books.  DBIC supports a
786       wide variety of more advanced operations to easily do things like
787       filtering and sorting the results.  For example, the following could be
788       used to sort the results by descending title:
789
790           $c->model('DB::Book')->search({}, {order_by => 'title DESC'});
791
792       Some other examples are provided in "Complex WHERE clauses" in
793       DBIx::Class::Manual::Cookbook, with additional information found at
794       "search" in DBIx::Class::ResultSet, "Searching" in
795       DBIx::Class::Manual::FAQ, DBIx::Class::Manual::Intro and
796       Catalyst::Model::DBIC::Schema.
797
798   Test Run The Application
799       First, let's enable an environment variable that causes DBIx::Class to
800       dump the SQL statements used to access the database.  This is a helpful
801       trick when you are trying to debug your database-oriented code.  Press
802       "Ctrl-C" to break out of the development server and enter:
803
804           $ export DBIC_TRACE=1
805           $ script/myapp_server.pl -r
806
807       This assumes you are using bash as your shell -- adjust accordingly if
808       you are using a different shell (for example, under tcsh, use "setenv
809       DBIC_TRACE 1").
810
811       NOTE: You can also set this in your code using
812       "$class->storage->debug(1);".  See DBIx::Class::Manual::Troubleshooting
813       for details (including options to log to a file instead of displaying
814       to the Catalyst development server log).
815
816       Then launch the Catalyst development server.  The log output should
817       display something like:
818
819           $ script/myapp_server.pl -r
820           [debug] Debug messages enabled
821           [debug] Statistics enabled
822           [debug] Loaded plugins:
823           .----------------------------------------------------------------------------.
824           | Catalyst::Plugin::ConfigLoader  0.30                                       |
825           | Catalyst::Plugin::StackTrace  0.11                                         |
826           '----------------------------------------------------------------------------'
827
828           [debug] Loaded dispatcher "Catalyst::Dispatcher"
829           [debug] Loaded engine "Catalyst::Engine"
830           [debug] Found home "/home/catalyst/MyApp"
831           [debug] Loaded Config "/home/catalyst/MyApp/myapp.conf"
832           [debug] Loaded components:
833           .-----------------------------------------------------------------+----------.
834           | Class                                                           | Type     |
835           +-----------------------------------------------------------------+----------+
836           | MyApp::Controller::Books                                        | instance |
837           | MyApp::Controller::Root                                         | instance |
838           | MyApp::Model::DB                                                | instance |
839           | MyApp::Model::DB::Author                                        | class    |
840           | MyApp::Model::DB::Book                                          | class    |
841           | MyApp::Model::DB::BookAuthor                                    | class    |
842           | MyApp::View::HTML                                               | instance |
843           '-----------------------------------------------------------------+----------'
844
845           [debug] Loaded Private actions:
846           .----------------------+--------------------------------------+--------------.
847           | Private              | Class                                | Method       |
848           +----------------------+--------------------------------------+--------------+
849           | /default             | MyApp::Controller::Root              | default      |
850           | /end                 | MyApp::Controller::Root              | end          |
851           | /index               | MyApp::Controller::Root              | index        |
852           | /books/index         | MyApp::Controller::Books             | index        |
853           | /books/list          | MyApp::Controller::Books             | list         |
854           '----------------------+--------------------------------------+--------------'
855
856           [debug] Loaded Path actions:
857           .-------------------------------------+--------------------------------------.
858           | Path                                | Private                              |
859           +-------------------------------------+--------------------------------------+
860           | /                                   | /default                             |
861           | /                                   | /index                               |
862           | /books                              | /books/index                         |
863           | /books/list                         | /books/list                          |
864           '-------------------------------------+--------------------------------------'
865
866           [info] MyApp powered by Catalyst 5.80020
867           HTTP::Server::PSGI: Accepting connections at http://0:3000
868
869       NOTE: Be sure you run the script/myapp_server.pl command from the
870       'base' directory of your application, not inside the script directory
871       itself or it will not be able to locate the myapp.db database file.
872       You can use a fully qualified or a relative path to locate the database
873       file, but we did not specify that when we ran the model helper earlier.
874
875       Some things you should note in the output above:
876
877       •   Catalyst::Model::DBIC::Schema dynamically created three model
878           classes, one to represent each of the three tables in our database
879           ("MyApp::Model::DB::Author", "MyApp::Model::DB::BookAuthor", and
880           "MyApp::Model::DB::Book").
881
882       •   The "list" action in our Books controller showed up with a path of
883           "/books/list".
884
885       Point your browser to <http://localhost:3000> and you should still get
886       the Catalyst welcome page.
887
888       Next, to view the book list, change the URL in your browser to
889       <http://localhost:3000/books/list>. You should get a list of the five
890       books loaded by the myapp01.sql script above without any formatting.
891       The rating for each book should appear on each row, but the "Author(s)"
892       column will still be blank (we will fill that in later).
893
894       Also notice in the output of the script/myapp_server.pl that
895       DBIx::Class used the following SQL to retrieve the data:
896
897           SELECT me.id, me.title, me.rating FROM book me
898
899       because we enabled DBIC_TRACE.
900
901       You now have the beginnings of a simple but workable web application.
902       Continue on to future sections and we will develop the application more
903       fully.
904

CREATE A WRAPPER FOR THE VIEW

906       When using TT, you can (and should) create a wrapper that will
907       literally wrap content around each of your templates.  This is
908       certainly useful as you have one main source for changing things that
909       will appear across your entire site/application instead of having to
910       edit many individual files.
911
912   Configure HTML.pm For The Wrapper
913       In order to create a wrapper, you must first edit your TT view and tell
914       it where to find your wrapper file.
915
916       Edit your TT view in lib/MyApp/View/HTML.pm and change it to match the
917       following:
918
919           __PACKAGE__->config(
920               # Change default TT extension
921               TEMPLATE_EXTENSION => '.tt2',
922               # Set the location for TT files
923               INCLUDE_PATH => [
924                       MyApp->path_to( 'root', 'src' ),
925                   ],
926               # Set to 1 for detailed timer stats in your HTML as comments
927               TIMER              => 0,
928               # This is your wrapper template located in the 'root/src'
929               WRAPPER => 'wrapper.tt2',
930           );
931
932   Create the Wrapper Template File and Stylesheet
933       Next you need to set up your wrapper template.  Basically, you'll want
934       to take the overall layout of your site and put it into this file.  For
935       the tutorial, open root/src/wrapper.tt2 and input the following:
936
937           <?xml version="1.0" encoding="UTF-8"?>
938           <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" [%#
939               %]"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
940           <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
941           <head>
942           <title>[% template.title or "My Catalyst App!" %]</title>
943           <link rel="stylesheet" href="[% c.uri_for('/static/css/main.css') %]" />
944           </head>
945
946           <body>
947           <div id="outer">
948           <div id="header">
949               [%# Your logo could go here -%]
950               <img src="[% c.uri_for('/static/images/btn_88x31_powered.png') %]" />
951               [%# Insert the page title -%]
952               <h1>[% template.title or site.title %]</h1>
953           </div>
954
955           <div id="bodyblock">
956           <div id="menu">
957               Navigation:
958               <ul>
959                   <li><a href="[% c.uri_for('/books/list') %]">Home</a></li>
960                   <li><a href="[% c.uri_for('/')
961                       %]" title="Catalyst Welcome Page">Welcome</a></li>
962               </ul>
963           </div><!-- end menu -->
964
965           <div id="content">
966               [%# Status and error messages %]
967               <span class="message">[% status_msg %]</span>
968               <span class="error">[% error_msg %]</span>
969               [%# This is where TT will stick all of your template's contents. -%]
970               [% content %]
971           </div><!-- end content -->
972           </div><!-- end bodyblock -->
973
974           <div id="footer">Copyright (c) your name goes here</div>
975           </div><!-- end outer -->
976
977           </body>
978           </html>
979
980       Notice the status and error message sections in the code above:
981
982           <span class="status">[% status_msg %]</span>
983           <span class="error">[% error_msg %]</span>
984
985       If we set either message in the Catalyst stash (e.g.,
986       "$c->stash->{status_msg} = 'Request was successful!'") it will be
987       displayed whenever any view used by that request is rendered.  The
988       "message" and "error" CSS styles can be customized to suit your needs
989       in the root/static/css/main.css file we create below.
990
991       Notes:
992
993       •   The Catalyst stash only lasts for a single HTTP request.  If you
994           need to retain information across requests you can use
995           Catalyst::Plugin::Session (we will use Catalyst sessions in the
996           Authentication chapter of the tutorial).
997
998       •   Although it is beyond the scope of this tutorial, you may wish to
999           use a JavaScript or AJAX tool such as jQuery
1000           (<https://www.jquery.com>) or Dojo (<https://dojotoolkit.org/>).
1001
1002       Create A Basic Stylesheet
1003
1004       First create a central location for stylesheets under the static
1005       directory:
1006
1007           $ mkdir root/static/css
1008
1009       Then open the file root/static/css/main.css (the file referenced in the
1010       stylesheet href link of our wrapper above) and add the following
1011       content:
1012
1013           #header {
1014               text-align: center;
1015           }
1016           #header h1 {
1017               margin: 0;
1018           }
1019           #header img {
1020               float: right;
1021           }
1022           #footer {
1023               text-align: center;
1024               font-style: italic;
1025               padding-top: 20px;
1026           }
1027           #menu {
1028               font-weight: bold;
1029               background-color: #ddd;
1030           }
1031           #menu ul {
1032               list-style: none;
1033               float: left;
1034               margin: 0;
1035               padding: 0 0 50% 5px;
1036               font-weight: normal;
1037               background-color: #ddd;
1038               width: 100px;
1039           }
1040           #content {
1041               margin-left: 120px;
1042           }
1043           .message {
1044               color: #390;
1045           }
1046           .error {
1047               color: #f00;
1048           }
1049
1050       You may wish to check out a "CSS Framework" like Emastic
1051       (<http://code.google.com/p/emastic/>) as a way to quickly provide lots
1052       of high-quality CSS functionality.
1053
1054   Test Run The Application
1055       Hit "Reload" in your web browser and you should now see a formatted
1056       version of our basic book list. (Again, the development server should
1057       have automatically restarted when you made changes to
1058       lib/MyApp/View/HTML.pm. If you are not using the "-r" option, you will
1059       need to hit "Ctrl-C" and manually restart it. Also note that the
1060       development server does NOT need to restart for changes to the TT and
1061       static files we created and edited in the "root" directory -- those
1062       updates are handled on a per-request basis.)
1063
1064       Although our wrapper and stylesheet are obviously very simple, you
1065       should see how it allows us to control the overall look of an entire
1066       website from two central files. To add new pages to the site, just
1067       provide a template that fills in the "content" section of our wrapper
1068       template -- the wrapper will provide the overall feel of the page.
1069
1070   Updating the Generated DBIx::Class Result Class Files
1071       If you take a look at the Schema files automatically generated by
1072       DBIx::Class::Schema::Loader, you will see that it has already defined
1073       "has_many" and "belongs_to" relationships on each side of our foreign
1074       keys. For example, take a look at lib/MyApp/Schema/Result/Book.pm and
1075       notice the following code:
1076
1077           =head1 RELATIONS
1078
1079           =head2 book_authors
1080
1081           Type: has_many
1082
1083           Related object: L<MyApp::Schema::Result::BookAuthor>
1084
1085           =cut
1086
1087           __PACKAGE__->has_many(
1088             "book_authors",
1089             "MyApp::Schema::Result::BookAuthor",
1090             { "foreign.book_id" => "self.id" },
1091             { cascade_copy => 0, cascade_delete => 0 },
1092           );
1093
1094       Each "Book" "has_many" "book_authors", where "BookAuthor" is the many-
1095       to-many table that allows each Book to have multiple Authors, and each
1096       Author to have multiple books.  The arguments to "has_many" are:
1097
1098       •   "book_authors" - The name for this relationship.  DBIC will create
1099           an accessor on the "Books" DBIC Row object with this name.
1100
1101       •   "MyApp::Schema::Result::BookAuthor" - The name of the DBIC model
1102           class referenced by this "has_many" relationship.
1103
1104       •   "foreign.book_id" - "book_id" is the name of the foreign key column
1105           in the foreign table that points back to this table.
1106
1107       •   "self.id" - "id" is the name of the column in this table that is
1108           referenced by the foreign key.
1109
1110       See "has_many" in DBIx::Class::Relationship for additional information.
1111       Note that you might see a "hand coded" version of the "has_many"
1112       relationship above expressed as:
1113
1114           __PACKAGE__->has_many(
1115             "book_authors",
1116             "MyApp::Schema::Result::BookAuthor",
1117             "book_id",
1118           );
1119
1120       Where the third argument is simply the name of the column in the
1121       foreign table.  However, the hashref syntax used by
1122       DBIx::Class::Schema::Loader is more flexible (for example, it can
1123       handle "multi-column foreign keys").
1124
1125       Note: If you are using older versions of SQLite and related DBIC tools,
1126       you will need to manually define your "has_many" and "belongs_to"
1127       relationships. We recommend upgrading to the versions specified above.
1128       :-)
1129
1130       Have a look at lib/MyApp/Schema/Result/BookAuthor.pm and notice that
1131       there is a "belongs_to" relationship defined that acts as the "mirror
1132       image" to the "has_many" relationship we just looked at above:
1133
1134           =head1 RELATIONS
1135
1136           =head2 book
1137
1138           Type: belongs_to
1139
1140           Related object: L<MyApp::Schema::Result::Book>
1141
1142           =cut
1143
1144           __PACKAGE__->belongs_to(
1145             "book",
1146             "MyApp::Schema::Result::Book",
1147             { id => "book_id" },
1148             { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" },
1149           );
1150
1151       The arguments are similar, but see "belongs_to" in
1152       DBIx::Class::Relationship for the details.
1153
1154       Although recent versions of SQLite and DBIx::Class::Schema::Loader
1155       automatically handle the "has_many" and "belongs_to" relationships,
1156       "many_to_many" relationship bridges (not technically a relationship)
1157       currently need to be manually inserted.  To add a "many_to_many"
1158       relationship bridge, first edit lib/MyApp/Schema/Result/Book.pm and add
1159       the following text below the "# You can replace this text..."  comment:
1160
1161           # many_to_many():
1162           #   args:
1163           #     1) Name of relationship bridge, DBIC will create accessor with this name
1164           #     2) Name of has_many() relationship this many_to_many() is shortcut for
1165           #     3) Name of belongs_to() relationship in model class of has_many() above
1166           #   You must already have the has_many() defined to use a many_to_many().
1167           __PACKAGE__->many_to_many(authors => 'book_authors', 'author');
1168
1169       Note: Be careful to put this code above the "1;" at the end of the
1170       file.  As with any Perl package, we need to end the last line with a
1171       statement that evaluates to "true".  This is customarily done with "1;"
1172       on a line by itself.
1173
1174       The "many_to_many" relationship bridge is optional, but it makes it
1175       easier to map a book to its collection of authors.  Without it, we
1176       would have to "walk" through the "book_author" table as in
1177       "$book->book_author->first->author->last_name" (we will see examples on
1178       how to use DBIx::Class objects in your code soon, but note that because
1179       "$book->book_author" can return multiple authors, we have to use
1180       "first" to display a single author).  "many_to_many" allows us to use
1181       the shorter "$book->author->first->last_name". Note that you cannot
1182       define a "many_to_many" relationship bridge without also having the
1183       "has_many" relationship in place.
1184
1185       Then edit lib/MyApp/Schema/Result/Author.pm and add the reverse
1186       "many_to_many" relationship bridge for "Author" as follows (again, be
1187       careful to put in above the "1;" but below the "# DO NOT MODIFY THIS OR
1188       ANYTHING ABOVE!" comment):
1189
1190           # many_to_many():
1191           #   args:
1192           #     1) Name of relationship bridge, DBIC will create accessor with this name
1193           #     2) Name of has_many() relationship this many_to_many() is shortcut for
1194           #     3) Name of belongs_to() relationship in model class of has_many() above
1195           #   You must already have the has_many() defined to use a many_to_many().
1196           __PACKAGE__->many_to_many(books => 'book_authors', 'book');
1197
1198   Run The Application
1199       Run the Catalyst development server script with the "DBIC_TRACE" option
1200       (it might still be enabled from earlier in the tutorial, but here is an
1201       alternate way to specify the trace option just in case):
1202
1203           $ DBIC_TRACE=1 script/myapp_server.pl -r
1204
1205       Make sure that the application loads correctly and that you see the
1206       three dynamically created model classes (one for each of the Result
1207       Classes we created).
1208
1209       Then hit the URL <http://localhost:3000/books/list> with your browser
1210       and be sure that the book list still displays correctly.
1211
1212       Note: You will not see the authors yet because the view isn't taking
1213       advantage of these relationships. Read on to the next section where we
1214       update the template to do that.
1215

UPDATING THE VIEW

1217       Let's add a new column to our book list page that takes advantage of
1218       the relationship information we manually added to our schema files in
1219       the previous section.  Edit root/src/books/list.tt2 and replace the
1220       "empty" table cell ""<td></td>"" with the following:
1221
1222           ...
1223           <td>
1224             [% # NOTE: See Chapter 4 for a better way to do this!                      -%]
1225             [% # First initialize a TT variable to hold a list.  Then use a TT FOREACH -%]
1226             [% # loop in 'side effect notation' to load just the last names of the     -%]
1227             [% # authors into the list. Note that the 'push' TT vmethod doesn't return -%]
1228             [% # a value, so nothing will be printed here.  But, if you have something -%]
1229             [% # in TT that does return a value and you don't want it printed, you     -%]
1230             [% # 1) assign it to a bogus value, or                                     -%]
1231             [% # 2) use the CALL keyword to call it and discard the return value.      -%]
1232             [% tt_authors = [ ];
1233                tt_authors.push(author.last_name) FOREACH author = book.authors %]
1234             [% # Now use a TT 'virtual method' to display the author count in parens   -%]
1235             [% # Note the use of the TT filter "| html" to escape dangerous characters -%]
1236             ([% tt_authors.size | html %])
1237             [% # Use another TT vmethod to join & print the names & comma separators   -%]
1238             [% tt_authors.join(', ') | html %]
1239           </td>
1240           ...
1241
1242       IMPORTANT NOTE: Again, you should keep as much "logic code" as possible
1243       out of your views.  This kind of logic belongs in your model (the same
1244       goes for controllers -- keep them as "thin" as possible and push all of
1245       the "complicated code" out to your model objects).  Avoid code like you
1246       see in the previous example -- we are only using it here to show some
1247       extra features in TT until we get to the more advanced model features
1248       we will see in Chapter 4 (see "EXPLORING THE POWER OF DBIC" in
1249       Catalyst::Manual::Tutorial::04_BasicCRUD).
1250
1251       Then hit "Reload" in your browser (note that you don't need to reload
1252       the development server or use the "-r" option when updating TT
1253       templates) and you should now see the number of authors each book has
1254       along with a comma-separated list of the authors' last names.  (If you
1255       didn't leave the development server running from the previous step, you
1256       will obviously need to start it before you can refresh your browser
1257       window.)
1258
1259       If you are still running the development server with "DBIC_TRACE"
1260       enabled, you should also now see five more "SELECT" statements in the
1261       debug output (one for each book as the authors are being retrieved by
1262       DBIx::Class):
1263
1264           SELECT me.id, me.title, me.rating FROM book me:
1265           SELECT author.id, author.first_name, author.last_name FROM book_author me
1266           JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '1'
1267           SELECT author.id, author.first_name, author.last_name FROM book_author me
1268           JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '2'
1269           SELECT author.id, author.first_name, author.last_name FROM book_author me
1270           JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '3'
1271           SELECT author.id, author.first_name, author.last_name FROM book_author me
1272           JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '4'
1273           SELECT author.id, author.first_name, author.last_name FROM book_author me
1274           JOIN author author ON author.id = me.author_id WHERE ( me.book_id = ? ): '5'
1275
1276       Also note in root/src/books/list.tt2 that we are using "| html", a type
1277       of TT filter, to escape characters such as < and > to &lt; and &gt; and
1278       avoid various types of dangerous hacks against your application.  In a
1279       real application, you would probably want to put "| html" at the end of
1280       every field where a user has control over the information that can
1281       appear in that field (and can therefore inject markup or code if you
1282       don't "neutralize" those fields).  In addition to "| html", Template
1283       Toolkit has a variety of other useful filters that can be found in the
1284       documentation for Template::Filters.  (While we are on the topic of
1285       security and escaping of dangerous values, one of the advantages of
1286       using tools like DBIC for database access or HTML::FormFu for form
1287       management [see Chapter 9] is that they automatically handle most
1288       escaping for you and therefore dramatically increase the security of
1289       your app.)
1290

RUNNING THE APPLICATION FROM THE COMMAND LINE

1292       In some situations, it can be useful to run your application and
1293       display a page without using a browser.  Catalyst lets you do this
1294       using the script/myapp_test.pl script.  Just supply the URL you wish to
1295       display and it will run that request through the normal controller
1296       dispatch logic and use the appropriate view to render the output
1297       (obviously, complex pages may dump a lot of text to your terminal
1298       window).  For example, if "Ctrl+C" out of the development server and
1299       then type:
1300
1301           $ script/myapp_test.pl "/books/list"
1302
1303       You should get the same text as if you visited
1304       <http://localhost:3000/books/list> with the normal development server
1305       and asked your browser to view the page source.  You can even pipe this
1306       HTML text output to a text-based browser using a command like:
1307
1308           $ script/myapp_test.pl "/books/list" | lynx -stdin
1309
1310       And you should see a fully rendered text-based view of your page.  (If
1311       you are following along in Debian 6, type "sudo aptitude -y install
1312       lynx" to install lynx.)  If you do start lynx, you can use the "Q" key
1313       to quit.
1314

OPTIONAL INFORMATION

1316       NOTE: The rest of this chapter of the tutorial is optional.  You can
1317       skip to Chapter 4, Basic CRUD, if you wish.
1318
1319   Using 'RenderView' for the Default View
1320       Once your controller logic has processed the request from a user, it
1321       forwards processing to your view in order to generate the appropriate
1322       response output.  Catalyst uses Catalyst::Action::RenderView by default
1323       to automatically perform this operation.  If you look in
1324       lib/MyApp/Controller/Root.pm, you should see the empty definition for
1325       the "sub end" method:
1326
1327           sub end : ActionClass('RenderView') {}
1328
1329       The following bullet points provide a quick overview of the
1330       "RenderView" process:
1331
1332Root.pm is designed to hold application-wide logic.
1333
1334       •   At the end of a given user request, Catalyst will call the most
1335           specific "end" method that's appropriate.  For example, if the
1336           controller for a request has an "end" method defined, it will be
1337           called.  However, if the controller does not define a controller-
1338           specific "end" method, the "global" "end" method in Root.pm will be
1339           called.
1340
1341       •   Because the definition includes an "ActionClass" attribute, the
1342           Catalyst::Action::RenderView logic will be executed after any code
1343           inside the definition of "sub end" is run.  See
1344           Catalyst::Manual::Actions for more information on "ActionClass".
1345
1346       •   Because "sub end" is empty, this effectively just runs the default
1347           logic in "RenderView".  However, you can easily extend the
1348           "RenderView" logic by adding your own code inside the empty method
1349           body ("{}") created by the Catalyst Helpers when we first ran the
1350           catalyst.pl to initialize our application.  See
1351           Catalyst::Action::RenderView for more detailed information on how
1352           to extend "RenderView" in "sub end".
1353
1354   RenderView's "dump_info" Feature
1355       One of the nice features of "RenderView" is that it automatically
1356       allows you to add "dump_info=1" to the end of any URL for your
1357       application and it will force the display of the "exception dump"
1358       screen to the client browser.  You can try this out by pointing your
1359       browser to this URL:
1360
1361           http://localhost:3000/books/list?dump_info=1
1362
1363       You should get a page with the following message at the top:
1364
1365           Caught exception in MyApp::Controller::Root->end "Forced debug -
1366           Scrubbed output at /usr/share/perl5/Catalyst/Action/RenderView.pm line 46."
1367
1368       Along with a summary of your application's state at the end of the
1369       processing for that request.  The "Stash" section should show a
1370       summarized version of the DBIC book model objects.  If desired, you can
1371       adjust the summarization logic (called "scrubbing" logic) -- see
1372       Catalyst::Action::RenderView for details.
1373
1374       Note that you shouldn't need to worry about "normal clients" using this
1375       technique to "reverse engineer" your application -- "RenderView" only
1376       supports the "dump_info=1" feature when your application is running in
1377       "-Debug" mode (something you won't do once you have your application
1378       deployed in production).
1379
1380   Using The Default Template Name
1381       By default, "Catalyst::View::TT" will look for a template that uses the
1382       same name as your controller action, allowing you to save the step of
1383       manually specifying the template name in each action.  For example,
1384       this would allow us to remove the "$c->stash->{template} =
1385       'books/list.tt2';" line of our "list" action in the Books controller.
1386       Open "lib/MyApp/Controller/Books.pm" in your editor and comment out
1387       this line to match the following (only the "$c->stash->{template}" line
1388       has changed):
1389
1390           =head2 list
1391
1392           Fetch all book objects and pass to books/list.tt2 in stash to be displayed
1393
1394           =cut
1395
1396           sub list :Local {
1397               # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
1398               # 'Context' that's used to 'glue together' the various components
1399               # that make up the application
1400               my ($self, $c) = @_;
1401
1402               # Retrieve all of the book records as book model objects and store in the
1403               # stash where they can be accessed by the TT template
1404               $c->stash(books => [$c->model('DB::Book')->all]);
1405
1406               # Set the TT template to use.  You will almost always want to do this
1407               # in your action methods (actions methods respond to user input in
1408               # your controllers).
1409               #$c->stash(template => 'books/list.tt2');
1410           }
1411
1412       You should now be able to access the <http://localhost:3000/books/list>
1413       URL as before.
1414
1415       NOTE: If you use the default template technique, you will not be able
1416       to use either the "$c->forward" or the "$c->detach" mechanisms (these
1417       are discussed in Chapter 2 and Chapter 9 of the Tutorial).
1418
1419       IMPORTANT: Make sure that you do not skip the following section before
1420       continuing to the next chapter 4 Basic CRUD.
1421
1422   Return To A Manually Specified Template
1423       In order to be able to use "$c->forward" and "$c->detach" later in the
1424       tutorial, you should remove the comment from the statement in "sub
1425       list" in lib/MyApp/Controller/Books.pm:
1426
1427           $c->stash(template => 'books/list.tt2');
1428
1429       Then delete the "TEMPLATE_EXTENSION" line in lib/MyApp/View/HTML.pm.
1430
1431       Check the <http://localhost:3000/books/list> URL in your browser.  It
1432       should look the same manner as with earlier sections.
1433
1434       You can jump to the next chapter of the tutorial here: Basic CRUD
1435

AUTHOR

1437       Kennedy Clark, "hkclark@gmail.com"
1438
1439       Feel free to contact the author for any errors or suggestions, but the
1440       best way to report issues is via the CPAN RT Bug system at
1441       <https://rt.cpan.org/Public/Dist/Display.html?Name=Catalyst-Manual>.
1442
1443       Copyright 2006-2011, Kennedy Clark, under the Creative Commons
1444       Attribution Share-Alike License Version 3.0
1445       (<https://creativecommons.org/licenses/by-sa/3.0/us/>).
1446
1447
1448
1449perl v5.34.0              Catalyst2:0:2M2a-n0u1a-l2:0:Tutorial::03_MoreCatalystBasics(3)
Impressum