Release commit for 5.9013
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / 02_CatalystBasics.pod
CommitLineData
d442cc9f 1=head1 NAME
2
3ab6187c 3Catalyst::Manual::Tutorial::02_CatalystBasics - Catalyst Tutorial - Chapter 2: Catalyst Application Development Basics
d442cc9f 4
5
6=head1 OVERVIEW
7
4b4d3884 8This is B<Chapter 2 of 10> for the Catalyst tutorial.
d442cc9f 9
10L<Tutorial Overview|Catalyst::Manual::Tutorial>
11
12=over 4
13
14=item 1
15
3ab6187c 16L<Introduction|Catalyst::Manual::Tutorial::01_Intro>
d442cc9f 17
18=item 2
19
3ab6187c 20B<02_Catalyst Basics>
d442cc9f 21
22=item 3
23
3ab6187c 24L<More Catalyst Basics|Catalyst::Manual::Tutorial::03_MoreCatalystBasics>
d442cc9f 25
26=item 4
27
3ab6187c 28L<Basic CRUD|Catalyst::Manual::Tutorial::04_BasicCRUD>
d442cc9f 29
30=item 5
31
3ab6187c 32L<Authentication|Catalyst::Manual::Tutorial::05_Authentication>
d442cc9f 33
34=item 6
35
3ab6187c 36L<Authorization|Catalyst::Manual::Tutorial::06_Authorization>
d442cc9f 37
38=item 7
39
3ab6187c 40L<Debugging|Catalyst::Manual::Tutorial::07_Debugging>
d442cc9f 41
42=item 8
43
3ab6187c 44L<Testing|Catalyst::Manual::Tutorial::08_Testing>
d442cc9f 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>
d442cc9f 53
54=back
55
56
57=head1 DESCRIPTION
58
040c4781 59In this chapter of the tutorial, we will create a very basic Catalyst
60web application, demonstrating a number of powerful capabilities, such
4b4d3884 61as:
d442cc9f 62
63=over 4
64
65=item * Helper Scripts
66
67Catalyst helper scripts that can be used to rapidly bootstrap the
68skeletal structure of an application.
69
70=item * MVC
71
72Model/View/Controller (MVC) provides an architecture that facilitates a
73clean "separation of control" between the different portions of your
74application. Given that many other documents cover this subject in
75detail, MVC will not be discussed in depth here (for an excellent
76introduction to MVC and general Catalyst concepts, please see
2217b252 77L<Catalyst::Manual::About>). In short:
d442cc9f 78
79=over 4
80
81=item * Model
82
83The model usually represents a data store. In most applications, the
84model equates to the objects that are created from and saved to your SQL
85database.
86
87=item * View
88
89The view takes model objects and renders them into something for the end
90user to look at. Normally this involves a template-generation tool that
91creates HTML for the user's web browser, but it could easily be code
040c4781 92that generates other forms such as PDF documents, e-mails, spreadsheets,
865d3efb 93or even "behind the scenes" formats such as XML and JSON.
d442cc9f 94
95=item * Controller
96
97As suggested by its name, the controller takes user requests and routes
98them to the necessary model and view.
99
100=back
101
102=item * ORM
103
104The use of Object-Relational Mapping (ORM) technology for database
105access. Specifically, ORM provides an automated and standardized means
444d6b27 106to persist and restore objects to/from a relational database and will
107automatically create our Catalyst model for use with a database.
d442cc9f 108
109=back
110
111You can checkout the source code for this example from the catalyst
112subversion repository as per the instructions in
2217b252 113L<Catalyst::Manual::Tutorial::01_Intro>.
d442cc9f 114
3533daff 115
d442cc9f 116=head1 CREATE A CATALYST PROJECT
117
040c4781 118Catalyst provides a number of helper scripts that can be used to quickly
119flesh out the basic structure of your application. All Catalyst projects
f4e9de4a 120begin with the F<catalyst.pl> helper (see
2217b252 121L<Catalyst::Helper> for more information on helpers).
040c4781 122Also note that as of Catalyst 5.7000, you will not have the helper
2217b252 123scripts unless you install both L<Catalyst::Runtime>
124and L<Catalyst::Devel>.
3533daff 125
f4e9de4a 126In this first chapter of the tutorial, use the Catalyst F<catalyst.pl>
4b4d3884 127script to initialize the framework for an application called C<Hello>:
3533daff 128
129 $ catalyst.pl Hello
130 created "Hello"
131 created "Hello/script"
132 created "Hello/lib"
133 created "Hello/root"
d442cc9f 134 ...
3533daff 135 created "Hello/script/hello_create.pl"
444d6b27 136 Change to application directory and Run "perl Makefile.PL" to make sure your install is complete
3533daff 137 $ cd Hello
d442cc9f 138
444d6b27 139Note: If you are using Strawberry Perl on Win32, drop the ".pl"
140from the end of the "catalyst.pl" command and simply use
141"catalyst Hello".
142
f4e9de4a 143The F<catalyst.pl> helper script will display the names of the
3533daff 144directories and files it creates:
145
146 Changes # Record of application changes
865d3efb 147 lib # Lib directory for your app's Perl modules
148 Hello # Application main code directory
7ce05098 149 Controller # Directory for Controller modules
3533daff 150 Model # Directory for Models
151 View # Directory for Views
152 Hello.pm # Base application module
153 Makefile.PL # Makefile to build application
45d511e0 154 hello.conf # Application configuration file
3533daff 155 README # README file
156 root # Equiv of htdocs, dir for templates, css, javascript
157 favicon.ico
158 static # Directory for static files
159 images # Directory for image files used in welcome screen
160 script # Directory for Perl scripts
161 hello_cgi.pl # To run your app as a cgi (not recommended)
162 hello_create.pl # To create models, views, controllers
163 hello_fastcgi.pl # To run app as a fastcgi program
164 hello_server.pl # The normal development server
165 hello_test.pl # Test your app from the command line
166 t # Directory for tests
7ce05098 167 01app.t # Test scaffold
168 02pod.t
169 03podcoverage.t
3533daff 170
171
040c4781 172Catalyst will "auto-discover" modules in the Controller, Model, and View
f4e9de4a 173directories. When you use the F<hello_create.pl> script it will create Perl
040c4781 174module scaffolds in those directories, plus test files in the "t"
175directory. The default location for templates is in the "root"
176directory. The scripts in the script directory will always start with
177the lowercased version of your application name. If your app is MaiTai,
178then the create script would be "maitai_create.pl".
3533daff 179
040c4781 180Though it's too early for any significant celebration, we already have a
181functioning application. We can use the Catalyst supplied script to
182start up a development server and view the default Catalyst page in your
183browser. All scripts in the script directory should be run from the base
184directory of your application, so change to the Hello directory.
3533daff 185
040c4781 186Run the following command to start up the built-in development web
187server (make sure you didn't forget the "C<cd Hello>" from the previous
188step):
d442cc9f 189
040c4781 190B<Note>: The "-r" argument enables reloading on code changes so you
191don't have to stop and start the server when you update code. See
40a01e5b 192C<perldoc script/hello_server.pl> or C<script/hello_server.pl --help>
193for additional options you might find helpful. Most of the rest of the
040c4781 194tutorial will assume that you are using "-r" when you start the
195development server, but feel free to manually start and stop it (use
196C<Ctrl-C> to breakout of the dev server) if you prefer.
0f1ac65e 197
198 $ script/hello_server.pl -r
d442cc9f 199 [debug] Debug messages enabled
865d3efb 200 [debug] Statistics enabled
d442cc9f 201 [debug] Loaded plugins:
202 .----------------------------------------------------------------------------.
b6e618b8 203 | Catalyst::Plugin::ConfigLoader 0.30 |
d442cc9f 204 '----------------------------------------------------------------------------'
7ce05098 205
d442cc9f 206 [debug] Loaded dispatcher "Catalyst::Dispatcher"
b6e618b8 207 [debug] Loaded engine "Catalyst::Engine"
477a6d5b 208 [debug] Found home "/home/catalyst/Hello"
209 [debug] Loaded Config "/home/catalyst/Hello/hello.conf"
d442cc9f 210 [debug] Loaded components:
211 .-----------------------------------------------------------------+----------.
212 | Class | Type |
213 +-----------------------------------------------------------------+----------+
3533daff 214 | Hello::Controller::Root | instance |
d442cc9f 215 '-----------------------------------------------------------------+----------'
7ce05098 216
d442cc9f 217 [debug] Loaded Private actions:
218 .----------------------+--------------------------------------+--------------.
219 | Private | Class | Method |
220 +----------------------+--------------------------------------+--------------+
3533daff 221 | /default | Hello::Controller::Root | default |
222 | /end | Hello::Controller::Root | end |
acbd7bdd 223 | /index | Hello::Controller::Root | index |
d442cc9f 224 '----------------------+--------------------------------------+--------------'
7ce05098 225
865d3efb 226 [debug] Loaded Path actions:
227 .-------------------------------------+--------------------------------------.
228 | Path | Private |
229 +-------------------------------------+--------------------------------------+
865d3efb 230 | / | /index |
08ae25e9 231 | / | /default |
865d3efb 232 '-------------------------------------+--------------------------------------'
7ce05098 233
b6e618b8 234 [info] Hello powered by Catalyst 5.90002
235 HTTP::Server::PSGI: Accepting connections at http://0:3000/
d442cc9f 236
040c4781 237Point your web browser to L<http://localhost:3000> (substituting a
238different hostname or IP address as appropriate) and you should be
239greeted by the Catalyst welcome screen (if you get some other welcome
240screen or an "Index" screen, you probably forgot to specify port 3000 in
241your URL). Information similar to the following should be appended to
242the logging output of the development server:
acbd7bdd 243
b6e618b8 244 [info] Hello powered by Catalyst 5.90002
245 HTTP::Server::PSGI: Accepting connections at http://0:3000/
246 [info] *** Request 1 (0.067/s) [19026] [Tue Aug 30 17:24:32 2011] ***
247 [debug] "GET" request for "/" from "192.168.245.2"
3dfcf16a 248 [debug] Path is "/"
b6e618b8 249 [debug] Response Code: 200; Content-Type: text/html; charset=utf-8; Content-Length: 5613
250 [info] Request took 0.040895s (24.453/s)
3dfcf16a 251 .------------------------------------------------------------+-----------.
252 | Action | Time |
253 +------------------------------------------------------------+-----------+
b6e618b8 254 | /index | 0.000916s |
255 | /end | 0.000877s |
3dfcf16a 256 '------------------------------------------------------------+-----------'
d442cc9f 257
040c4781 258B<Note>: Press C<Ctrl-C> to break out of the development server if
7a296c6f 259necessary.
d442cc9f 260
261
3533daff 262=head1 HELLO WORLD
d442cc9f 263
3533daff 264=head2 The Simplest Way
d442cc9f 265
040c4781 266The Root.pm controller is a place to put global actions that usually
f4e9de4a 267execute on the root URL. Open the F<lib/Hello/Controller/Root.pm> file
040c4781 268in your editor. You will see the "index" subroutine, which is
269responsible for displaying the welcome screen that you just saw in your
270browser.
d442cc9f 271
865d3efb 272 sub index :Path :Args(0) {
3533daff 273 my ( $self, $c ) = @_;
7ce05098 274
865d3efb 275 # Hello World
3533daff 276 $c->response->body( $c->welcome_message );
d442cc9f 277 }
278
040c4781 279Later on you'll want to change that to something more reasonable, such
280as a "404" message or a redirect, but for now just leave it alone.
281
282The "C<$c>" here refers to the Catalyst context, which is used to access
283the Catalyst application. In addition to many other things, the Catalyst
284context provides access to "response" and "request" objects. (See
89a65964 285L<Catalyst::Runtime>, L<Catalyst::Response>, and
2217b252 286L<Catalyst::Request>)
040c4781 287
429d1caf 288C<< $c->response->body >> sets the HTTP response (see
2217b252 289L<Catalyst::Response>), while
429d1caf 290C<< $c->welcome_message >> is a special method that returns the welcome
040c4781 291message that you saw in your browser.
292
080bb620 293The "C<:Path :Args(0)>" after the method name are attributes which
040c4781 294determine which URLs will be dispatched to this method. (You might see
295":Private" if you are using an older version of Catalyst, but using that
296with "default" or "index" is currently deprecated. If so, you should
297also probably upgrade before continuing the tutorial.)
298
299Some MVC frameworks handle dispatching in a central place. Catalyst, by
300policy, prefers to handle URL dispatching with attributes on controller
301methods. There is a lot of flexibility in specifying which URLs to
302match. This particular method will match all URLs, because it doesn't
303specify the path (nothing comes after "Path"), but will only accept a
080bb620 304URL without any args because of the "C<:Args(0)>".
040c4781 305
306The default is to map URLs to controller names, and because of the way
307that Perl handles namespaces through package names, it is simple to
308create hierarchical structures in Catalyst. This means that you can
309create controllers with deeply nested actions in a clean and logical
310way. For example, the URL C<http://hello.com/admin/articles/create> maps
311to the package C<Hello::Controller::Admin::Articles>, and the C<create>
312method.
313
b6e618b8 314While you leave the C<script/hello_server.pl -r> command running the
0f387d99 315development server in one window (don't forget the "-r" at the end!),
b6e618b8 316open another window and add the following subroutine to your
f4e9de4a 317F<lib/Hello/Controller/Root.pm> file:
d442cc9f 318
3d0b2e0b 319 sub hello :Global {
3533daff 320 my ( $self, $c ) = @_;
7ce05098 321
3533daff 322 $c->response->body("Hello, World!");
323 }
d442cc9f 324
acbd7bdd 325B<TIP>: See Appendix 1 for tips on removing the leading spaces when
326cutting and pasting example code from POD-based documents.
327
b6e618b8 328Notice in the window running the Development Server that you should
329get output similar to the following:
3533daff 330
e7cfb0cc 331 Saw changes to the following files:
477a6d5b 332 - /home/catalyst/Hello/lib/Hello/Controller/Root.pm (modify)
7ce05098 333
e7cfb0cc 334 Attempting to restart the server
0ed3df53 335 ...
e7cfb0cc 336 [debug] Loaded Private actions:
337 .----------------------+--------------------------------------+--------------.
338 | Private | Class | Method |
339 +----------------------+--------------------------------------+--------------+
340 | /default | Hello::Controller::Root | default |
341 | /end | Hello::Controller::Root | end |
342 | /index | Hello::Controller::Root | index |
343 | /hello | Hello::Controller::Root | hello |
344 '----------------------+--------------------------------------+--------------'
e7cfb0cc 345 ...
346
b6e618b8 347The development server noticed the change in C<Hello::Controller::Root>
348and automatically restarted itself.
349
040c4781 350Go to L<http://localhost:3000/hello> to see "Hello, World!". Also
351notice that the newly defined 'hello' action is listed under "Loaded
7a296c6f 352Private actions" in the development server debug output.
353
865d3efb 354
3533daff 355=head2 Hello, World! Using a View and a Template
356
040c4781 357In the Catalyst world a "View" itself is not a page of XHTML or a
358template designed to present a page to a browser. Rather, it is the
0f387d99 359module that determines the I<type> of view -- HTML, PDF, XML, etc. For
7a3a3026 360the thing that generates the I<content> of that view (such as a
eec35f62 361Template Toolkit template file), the actual templates go under the
865d3efb 362"root" directory.
3533daff 363
364To create a TT view, run:
365
1edbdee6 366 $ script/hello_create.pl view HTML TT
3533daff 367
f4e9de4a 368This creates the F<lib/Hello/View/HTML.pm> module, which is a subclass
cacb3819 369of L<Catalyst::View::TT>.
1435672d 370
371=over 4
372
373=item *
374
375The "view" keyword tells the create script that you are creating a view.
376
377=item *
378
1edbdee6 379The first argument "HTML" tells the script to name the View module "HTML.pm",
380which is a commonly used name for TT views. You can name it anything you want,
381such as "MyView.pm". If you have more than one view, be sure to set the
2217b252 382default_view in Hello.pm (See L<Catalyst::View::TT> for more
1edbdee6 383details on setting this).
1435672d 384
385=item *
386
040c4781 387The final "TT" tells Catalyst the I<type> of the view, with "TT"
eec35f62 388indicating that you want to use a Template Toolkit view.
1435672d 389
390=back
391
f4e9de4a 392If you look at F<lib/Hello/View/HTML.pm> you will find that it only
444d6b27 393contains a config statement to set the TT extension to ".tt".
3533daff 394
040c4781 395Now that the HTML.pm "View" exists, Catalyst will autodiscover it and be
396able to use it to display the view templates using the "process" method
cacb3819 397that it inherits from the L<Catalyst::View::TT> class.
3533daff 398
0f387d99 399Template Toolkit is a very full-featured template facility, with
040c4781 400excellent documentation at L<http://template-toolkit.org/>, but since
401this is not a TT tutorial, we'll stick to only basic TT usage here (and
402explore some of the more common TT features in later chapters of the
403tutorial).
3533daff 404
f4e9de4a 405Create a F<root/hello.tt> template file (put it in the C<root> under the
040c4781 406C<Hello> directory that is the base of your application). Here is a
407simple sample:
af0a93cf 408
3533daff 409 <p>
1435672d 410 This is a TT view template, called '[% template.name %]'.
3533daff 411 </p>
412
040c4781 413[% and %] are markers for the TT parts of the template. Inside you can
414access Perl variables and classes, and use TT directives. In this case,
415we're using a special TT variable that defines the name of the template
f4e9de4a 416file (F<hello.tt>). The rest of the template is normal HTML.
1435672d 417
f4e9de4a 418Change the hello method in F<lib/Hello/Controller/Root.pm> to the
1435672d 419following:
3533daff 420
3d0b2e0b 421 sub hello :Global {
3533daff 422 my ( $self, $c ) = @_;
7ce05098 423
61cb69fd 424 $c->stash(template => 'hello.tt');
3533daff 425 }
d442cc9f 426
429d1caf 427This time, instead of doing C<< $c->response->body() >>, you are
040c4781 428setting the value of the "template" hash key in the Catalyst "stash", an
429area for putting information to share with other parts of your
430application. The "template" key determines which template will be
431displayed at the end of the request cycle. Catalyst controllers have a
432default "end" action for all methods which causes the first (or default)
429d1caf 433view to be rendered (unless there's a C<< $c->response->body() >>
040c4781 434statement). So your template will be magically displayed at the end of
435your method.
d442cc9f 436
7a296c6f 437After saving the file, the development server should automatically
040c4781 438restart (again, the tutorial is written to assume that you are using the
439"-r" option -- manually restart it if you aren't), and look at
0f387d99 440L<http://localhost:3000/hello> in your web browser again. You should see
441the template that you just created.
040c4781 442
443B<TIP:> If you keep the server running with "-r" in a "background
0f387d99 444window," don't let that window get totally hidden... if you have a
040c4781 445syntax error in your code, the debug server output will contain the
af0a93cf 446error information.
447
ddfbd850 448B<Note:> You will probably run into a variation of the "stash"
449statement above that looks like:
450
451 $c->stash->{template} = 'hello.tt';
452
453Although this style is still relatively common, the approach we
454used previous is becoming more common because it allows you to
455set multiple stash variables in one line. For example:
456
7ce05098 457 $c->stash(template => 'hello.tt', foo => 'bar',
ddfbd850 458 another_thing => 1);
459
460You can also set multiple stash values with a hashref:
461
7ce05098 462 $c->stash({template => 'hello.tt', foo => 'bar',
ddfbd850 463 another_thing => 1});
464
429d1caf 465Any of these formats work, but the C<< $c->stash(name => value); >>
040c4781 466style is growing in popularity -- you may wish to use it all the time
467(even when you are only setting a single value).
ddfbd850 468
7a296c6f 469
3533daff 470=head1 CREATE A SIMPLE CONTROLLER AND AN ACTION
d442cc9f 471
3533daff 472Create a controller named "Site" by executing the create script:
d442cc9f 473
3533daff 474 $ script/hello_create.pl controller Site
d442cc9f 475
f4e9de4a 476This will create a F<lib/Hello/Controller/Site.pm> file (and a test
0f387d99 477file). If you bring Site.pm up in your editor, you can see that
478there's not much there to see.
d442cc9f 479
f4e9de4a 480In F<lib/Hello/Controller/Site.pm>, add the following method:
d442cc9f 481
3d0b2e0b 482 sub test :Local {
3533daff 483 my ( $self, $c ) = @_;
7ce05098 484
7a296c6f 485 $c->stash(username => 'John',
0ed3df53 486 template => 'site/test.tt');
d442cc9f 487 }
488
040c4781 489Notice the "Local" attribute on the C<test> method. This will cause the
490C<test> action (now that we have assigned an "action type" to the method
491it appears as a "controller action" to Catalyst) to be executed on the
492"controller/method" URL, or, in this case, "site/test". We will see
493additional information on controller actions throughout the rest of the
494tutorial, but if you are curious take a look at
1435672d 495L<Catalyst::Manual::Intro/Actions>.
496
040c4781 497It's not actually necessary to set the template value as we do here. By
498default TT will attempt to render a template that follows the naming
499pattern "controller/method.tt", and we're following that pattern here.
500However, in other situations you will need to specify the template (such
501as if you've "forwarded" to the method, or if it doesn't follow the
502default naming convention).
1435672d 503
040c4781 504We've also put the variable "username" into the stash, for use in the
1435672d 505template.
d442cc9f 506
6bd34389 507Make a subdirectory "site" in the "root" directory.
d442cc9f 508
6bd34389 509 $ mkdir root/site
510
f4e9de4a 511Create a new template file in that directory named F<root/site/test.tt>
6bd34389 512and include a line like:
d442cc9f 513
6bd34389 514 <p>Hello, [% username %]!</p>
d442cc9f 515
040c4781 516Once the server automatically restarts, notice in the server output that
517C</site/test> is listed in the Loaded Path actions. Go to
6bd34389 518L<http://localhost:3000/site/test> in your browser and you should see
519your test.tt file displayed, including the name "John" that you set in
520the controller.
7a296c6f 521
d442cc9f 522
24acc5d7 523You can jump to the next chapter of the tutorial here:
524L<More Catalyst Basics|Catalyst::Manual::Tutorial::03_MoreCatalystBasics>
525
3533daff 526=head1 AUTHORS
d442cc9f 527
3533daff 528Gerda Shank, C<gerda.shank@gmail.com>
d442cc9f 529Kennedy Clark, C<hkclark@gmail.com>
530
53243324 531Feel free to contact the author for any errors or suggestions, but the
532best way to report issues is via the CPAN RT Bug system at
bb0999d3 533L<https://rt.cpan.org/Public/Dist/Display.html?Name=Catalyst-Manual>.
53243324 534
bb0999d3 535Copyright 2006-2011, Kennedy Clark, under the
ec3ef4ad 536Creative Commons Attribution Share-Alike License Version 3.0
56a12748 537(L<https://creativecommons.org/licenses/by-sa/3.0/us/>).