Commit | Line | Data |
d442cc9f |
1 | =head1 NAME |
2 | |
3 | Catalyst::Manual::Tutorial::CatalystBasics - Catalyst Tutorial - Part 2: Catalyst Application Development Basics |
4 | |
5 | |
6 | =head1 OVERVIEW |
7 | |
3533daff |
8 | This is B<Part 2 of 10> for the Catalyst tutorial. |
d442cc9f |
9 | |
10 | L<Tutorial Overview|Catalyst::Manual::Tutorial> |
11 | |
12 | =over 4 |
13 | |
14 | =item 1 |
15 | |
16 | L<Introduction|Catalyst::Manual::Tutorial::Intro> |
17 | |
18 | =item 2 |
19 | |
20 | B<Catalyst Basics> |
21 | |
22 | =item 3 |
23 | |
3533daff |
24 | L<More Catalyst Basics|Catalyst::Manual::Tutorial::MoreCatalystBasics> |
d442cc9f |
25 | |
26 | =item 4 |
27 | |
3533daff |
28 | L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD> |
d442cc9f |
29 | |
30 | =item 5 |
31 | |
3533daff |
32 | L<Authentication|Catalyst::Manual::Tutorial::Authentication> |
d442cc9f |
33 | |
34 | =item 6 |
35 | |
3533daff |
36 | L<Authorization|Catalyst::Manual::Tutorial::Authorization> |
d442cc9f |
37 | |
38 | =item 7 |
39 | |
3533daff |
40 | L<Debugging|Catalyst::Manual::Tutorial::Debugging> |
d442cc9f |
41 | |
42 | =item 8 |
43 | |
3533daff |
44 | L<Testing|Catalyst::Manual::Tutorial::Testing> |
d442cc9f |
45 | |
46 | =item 9 |
47 | |
3533daff |
48 | L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD> |
49 | |
50 | =item 10 |
51 | |
d442cc9f |
52 | L<Appendices|Catalyst::Manual::Tutorial::Appendices> |
53 | |
54 | =back |
55 | |
56 | |
57 | =head1 DESCRIPTION |
58 | |
3533daff |
59 | In this part of the tutorial, we will create a very basic Catalyst web |
60 | application, demonstrating a number of powerful capabilities, such as: |
d442cc9f |
61 | |
62 | =over 4 |
63 | |
64 | =item * Helper Scripts |
65 | |
66 | Catalyst helper scripts that can be used to rapidly bootstrap the |
67 | skeletal structure of an application. |
68 | |
69 | =item * MVC |
70 | |
71 | Model/View/Controller (MVC) provides an architecture that facilitates a |
72 | clean "separation of control" between the different portions of your |
73 | application. Given that many other documents cover this subject in |
74 | detail, MVC will not be discussed in depth here (for an excellent |
75 | introduction to MVC and general Catalyst concepts, please see |
d0496197 |
76 | L<Catalyst::Manual::About|Catalyst::Manual::About>. In short: |
d442cc9f |
77 | |
78 | =over 4 |
79 | |
80 | =item * Model |
81 | |
82 | The model usually represents a data store. In most applications, the |
83 | model equates to the objects that are created from and saved to your SQL |
84 | database. |
85 | |
86 | =item * View |
87 | |
88 | The view takes model objects and renders them into something for the end |
89 | user to look at. Normally this involves a template-generation tool that |
90 | creates HTML for the user's web browser, but it could easily be code |
91 | that generates other forms such as PDF documents, e-mails, or Excel |
92 | spreadsheets. |
93 | |
94 | =item * Controller |
95 | |
96 | As suggested by its name, the controller takes user requests and routes |
97 | them to the necessary model and view. |
98 | |
99 | =back |
100 | |
101 | =item * ORM |
102 | |
103 | The use of Object-Relational Mapping (ORM) technology for database |
104 | access. Specifically, ORM provides an automated and standardized means |
105 | to persist and restore objects to/from a relational database. |
106 | |
107 | =back |
108 | |
109 | You can checkout the source code for this example from the catalyst |
110 | subversion repository as per the instructions in |
d0496197 |
111 | L<Catalyst::Manual::Tutorial::Intro|Catalyst::Manual::Tutorial::Intro> |
d442cc9f |
112 | |
3533daff |
113 | |
d442cc9f |
114 | =head1 CREATE A CATALYST PROJECT |
115 | |
3533daff |
116 | Catalyst provides a number of helper scripts that can be used to |
117 | quickly flesh out the basic structure of your application. All |
118 | Catalyst projects begin with the C<catalyst.pl> helper (see |
119 | L<Catalyst::Helper|Catalyst::Helper> for more information on helpers). |
120 | Also note that as of Catalyst 5.7000, you will not have the helper |
121 | scripts unless you install both L<Catalyst::Runtime|Catalyst::Runtime> |
122 | and L<Catalyst::Devel|Catalyst::Devel>. |
123 | |
124 | In this first part of the tutorial, use the Catalyst |
125 | C<catalyst.pl> script to initialize the framework for an |
126 | application called C<Hello>: |
127 | |
128 | $ catalyst.pl Hello |
129 | created "Hello" |
130 | created "Hello/script" |
131 | created "Hello/lib" |
132 | created "Hello/root" |
d442cc9f |
133 | ... |
3533daff |
134 | created "Hello/script/hello_create.pl" |
135 | $ cd Hello |
d442cc9f |
136 | |
137 | The C<catalyst.pl> helper script will display the names of the |
3533daff |
138 | directories and files it creates: |
139 | |
140 | Changes # Record of application changes |
141 | lib # Lib directory for Perl modules |
142 | Hello # Application code directory |
143 | Controller # Directory for Controller modules |
144 | Model # Directory for Models |
145 | View # Directory for Views |
146 | Hello.pm # Base application module |
147 | Makefile.PL # Makefile to build application |
45d511e0 |
148 | hello.conf # Application configuration file |
3533daff |
149 | README # README file |
150 | root # Equiv of htdocs, dir for templates, css, javascript |
151 | favicon.ico |
152 | static # Directory for static files |
153 | images # Directory for image files used in welcome screen |
154 | script # Directory for Perl scripts |
155 | hello_cgi.pl # To run your app as a cgi (not recommended) |
156 | hello_create.pl # To create models, views, controllers |
157 | hello_fastcgi.pl # To run app as a fastcgi program |
158 | hello_server.pl # The normal development server |
159 | hello_test.pl # Test your app from the command line |
160 | t # Directory for tests |
161 | 01app.t # Test scaffold |
162 | 02pod.t |
163 | 03podcoverage.t |
164 | |
165 | |
166 | Catalyst will "auto-discover" modules in the Controller, Model, and |
167 | View directories. When you use the hello_create.pl script it will |
168 | create Perl module scaffolds in those directories, plus test files in |
169 | the "t" directory. The default location for templates is in the "root" |
170 | directory. The scripts in the script directory will always start with |
171 | the lowercased version of your application name. If your app is |
172 | MaiTai, then the create script would be "maitai_create.pl". |
173 | |
174 | Though it's too early for any significant celebration, we already have |
175 | a functioning application. We can use the Catalyst supplied script to |
176 | start up a development server and view the default Catalyst page in |
177 | your browser. All scripts in the script directory should be run from |
178 | the base directory of your application, so change to the Hello |
179 | directory. |
180 | |
181 | Run the following command to start up the built-in development web |
182 | server: |
d442cc9f |
183 | |
3533daff |
184 | $ script/hello_server.pl |
d442cc9f |
185 | [debug] Debug messages enabled |
186 | [debug] Loaded plugins: |
187 | .----------------------------------------------------------------------------. |
3533daff |
188 | | Catalyst::Plugin::ConfigLoader 0.17 | |
189 | | Catalyst::Plugin::Static::Simple 0.20 | |
d442cc9f |
190 | '----------------------------------------------------------------------------' |
191 | |
192 | [debug] Loaded dispatcher "Catalyst::Dispatcher" |
193 | [debug] Loaded engine "Catalyst::Engine::HTTP" |
3533daff |
194 | [debug] Found home "/home/me/Hello" |
e13f83cc |
195 | [debug] Loaded Config "/home/me/Hello/hello.conf" |
d442cc9f |
196 | [debug] Loaded components: |
197 | .-----------------------------------------------------------------+----------. |
198 | | Class | Type | |
199 | +-----------------------------------------------------------------+----------+ |
3533daff |
200 | | Hello::Controller::Root | instance | |
d442cc9f |
201 | '-----------------------------------------------------------------+----------' |
202 | |
203 | [debug] Loaded Private actions: |
204 | .----------------------+--------------------------------------+--------------. |
205 | | Private | Class | Method | |
206 | +----------------------+--------------------------------------+--------------+ |
3533daff |
207 | | /default | Hello::Controller::Root | default | |
208 | | /end | Hello::Controller::Root | end | |
d442cc9f |
209 | '----------------------+--------------------------------------+--------------' |
210 | |
3533daff |
211 | [info] Hello powered by Catalyst 5.7011 |
d442cc9f |
212 | You can connect to your server at http://localhost:3000 |
213 | |
3533daff |
214 | Point your web browser to |
215 | L<http://localhost:3000|http://localhost:3000> (substituting a |
d442cc9f |
216 | different hostname or IP address as appropriate) and you should be |
217 | greeted by the Catalyst welcome screen. Information similar to the |
218 | following should be appended to the logging output of the development |
219 | server: |
220 | |
3533daff |
221 | [info] *** Request 1 (1.000/s) [10301] [Sun May 18 10:11:36 2008] *** |
d442cc9f |
222 | [debug] "GET" request for "/" from "127.0.0.1" |
3533daff |
223 | [info] Request took 0.017964s (55.667/s) |
d442cc9f |
224 | .----------------------------------------------------------------+-----------. |
225 | | Action | Time | |
226 | +----------------------------------------------------------------+-----------+ |
3533daff |
227 | | /default | 0.000540s | |
228 | | /end | 0.001246s | |
d442cc9f |
229 | '----------------------------------------------------------------+-----------' |
230 | |
231 | Press Ctrl-C to break out of the development server. |
232 | |
233 | |
3533daff |
234 | =head1 HELLO WORLD |
d442cc9f |
235 | |
3533daff |
236 | =head2 The Simplest Way |
d442cc9f |
237 | |
3533daff |
238 | The Root.pm controller is a place to put global actions that usually |
239 | execute on the root URL. Open the C<lib/Hello/Controller/Root.pm> file in |
240 | your editor. You will see the "default" subroutine, which is |
241 | responsible for displaying the welcome screen that you just saw in |
242 | your browser. Later on you'll want to change that to something more |
243 | reasonable, such as a "404" message but for now just leave it alone. |
d442cc9f |
244 | |
ae492862 |
245 | sub default :Path :Args { |
3533daff |
246 | my ( $self, $c ) = @_; |
d0496197 |
247 | |
3533daff |
248 | $c->response->body( $c->welcome_message ); |
d442cc9f |
249 | } |
250 | |
3533daff |
251 | The "C<$c>" here refers to the Catalyst context, which is used to |
252 | access the Catalyst application. In addition to many other things, |
253 | the Catalyst context provides access to "response" and "request" |
d0496197 |
254 | objects. (See L<Catalyst|Catalyst>, |
255 | L<Catalyst::Response|Catalyst::Response>, and |
256 | L<Catalyst::Request|Catalyst::Request>) |
d442cc9f |
257 | |
14e5ed66 |
258 | C<$c-E<gt>response-E<gt>body> sets the HTTP response (see |
259 | L<Catalyst::Response|Catalyst::Response>), while C<$c-E<gt>welcome_message> |
d0496197 |
260 | is a special method that returns the welcome message that you saw in |
261 | your browser. |
d442cc9f |
262 | |
ae492862 |
263 | The ":Path :Args" after the method name are attributes which determine |
3533daff |
264 | which URLs will be dispatched to this method. (Depending on your version of |
265 | Catalyst, it used to say "Private" but using that with default is |
266 | currently deprecated.) |
d442cc9f |
267 | |
3533daff |
268 | Some MVC frameworks handle dispatching in a central place. Catalyst, |
269 | by policy, prefers to handle URL dispatching with attributes on |
270 | controller methods. There is a lot of flexibility in specifying which |
271 | URLs to match. This particular method will match all URLs, because it |
272 | doesn't specify the path (nothing comes after "Path"), and will accept |
273 | any number of args (nothing after args). |
d442cc9f |
274 | |
3533daff |
275 | The default is to map URLs to controller names, and because of |
276 | the way that Perl handles namespaces through package names, |
277 | it is simple to create hierarchical structures in |
278 | Catalyst. This means that you can create controllers with deeply |
279 | nested actions in a clean and logical way. |
d442cc9f |
280 | |
3533daff |
281 | For example, the URL C<http://hello.com/admin/articles/create> maps |
282 | to the package C<Hello::Controller::Admin::Articles>, and the C<create> |
283 | method. |
d442cc9f |
284 | |
d442cc9f |
285 | |
d0496197 |
286 | Add the following subroutine to your C<lib/Hello/Controller/Root.pm> |
287 | file: |
d442cc9f |
288 | |
3533daff |
289 | sub hello : Global { |
290 | my ( $self, $c ) = @_; |
d0496197 |
291 | |
3533daff |
292 | $c->response->body("Hello, World!"); |
293 | } |
d442cc9f |
294 | |
3533daff |
295 | Here you're sending your own string to the webpage. |
296 | |
297 | Save the file, start the server (stop and restart it if it's still |
d0496197 |
298 | up), and go to L<http://localhost:3000/hello> to |
3533daff |
299 | see "Hello, World!" |
300 | |
301 | =head2 Hello, World! Using a View and a Template |
302 | |
303 | In the Catalyst world a "View" is not a page of XHTML or a template |
304 | designed to present a page to a browser. It is the module that |
305 | determines the type of view--HTML, pdf, XML. For the case of a |
306 | template view (such as the default Toolkit Template) the actual |
307 | templates go under the "root" directory. |
308 | |
309 | To create a TT view, run: |
310 | |
311 | $ script/hello_create.pl view TT TT |
312 | |
313 | This creates the C<lib/Hello/View/TT.pm> module, which is a subclass of |
314 | C<Catalyst::View::TT>. The "view" keyword tells the create script that |
315 | you are creating a view, the first "TT" tells it that you are creating |
316 | a Template Toolkit view, and the second "TT" tells the script to name |
317 | the View module "TT.pm", which is a commonly used name for TT views. |
318 | (You can name it anything you want, such as "HTML.pm".) If you look at |
319 | TT.pm, you will find that it only contains a config statement to set |
320 | the TT extension to ".tt". |
321 | |
322 | Now that the TT.pm "View" exists, Catalyst will autodiscover it and be |
323 | able to use it to display the view templates, using the "process" |
324 | method that it inherits from the C<Catalyst::View::TT class>. |
325 | |
c010ae0d |
326 | Template Toolkit is a very full featured template facility, with |
327 | excellent documentation at |
d0496197 |
328 | L<http://template-tookit.org/>, |
3533daff |
329 | but since this is not a TT tutorial, we'll stick to only basic TT |
330 | usage here (and explore some of the more common TT features in later |
331 | parts of the tutorial). |
332 | |
333 | Create a C<root/hello.tt> template file (put it in the C<root> under |
334 | the C<Hello> directory that is the base of your application). Here is |
335 | a simple sample: |
336 | |
337 | [% META title = 'Hello, World!' %] |
338 | <p> |
d0496197 |
339 | This is a TT view template, located in the 'root/' directory. |
3533daff |
340 | </p> |
341 | |
342 | [% and %] are markers for the TT parts of the template. Inside you can |
343 | access Perl variables and classes, and use TT directives. The rest of |
d0496197 |
344 | the template is normal HTML. Change the hello method in |
345 | C<lib/Hello/Controller/Root.pm> to the following: |
3533daff |
346 | |
347 | sub hello : Global { |
348 | my ( $self, $c ) = @_; |
d0496197 |
349 | |
3533daff |
350 | $c->stash->{template} = 'hello.tt'; |
351 | } |
d442cc9f |
352 | |
14e5ed66 |
353 | This time, instead of doing C<$c-E<gt>response->body()>, you are setting |
3533daff |
354 | the value of the "template" hash key in the Catalyst "stash", an area |
355 | for putting information to share with other parts of your application. |
356 | The "template" key determines which template will be displayed at the |
357 | end of the method. Catalyst controllers have a default "end" action |
358 | for all methods which causes the first (or default) view to be |
14e5ed66 |
359 | rendered (unless there's a C<$c-E<gt>response->body()> statement). So your |
3533daff |
360 | template will be magically displayed at the end of your method. |
d442cc9f |
361 | |
3533daff |
362 | After saving the file, restart the development server, and look at |
d0496197 |
363 | L<http://localhost:3000/hello> again. You should |
3533daff |
364 | see the template that you just made. |
d442cc9f |
365 | |
d442cc9f |
366 | |
3533daff |
367 | =head1 CREATE A SIMPLE CONTROLLER AND AN ACTION |
d442cc9f |
368 | |
3533daff |
369 | Create a controller named "Site" by executing the create script: |
d442cc9f |
370 | |
3533daff |
371 | $ script/hello_create.pl controller Site |
d442cc9f |
372 | |
3533daff |
373 | This will create a C<lib/Hello/Controller/Site.pm> file (and a test |
374 | file). Bring Site.pm up in your editor, and you can see that there's |
375 | not much there. Most people probably don't bother to use the create |
376 | script to make controllers after they're used to using Catalyst. |
d442cc9f |
377 | |
d0496197 |
378 | In C<lib/Hello/Controller/Site.pm>, add the following method: |
d442cc9f |
379 | |
3533daff |
380 | sub test : Local { |
381 | my ( $self, $c ) = @_; |
d0496197 |
382 | |
3533daff |
383 | $c->stash->{username} = "John"; |
384 | $c->stash->{template} = 'site/test.tt'; |
d442cc9f |
385 | } |
386 | |
3533daff |
387 | Notice the "Local" attribute on the method. This will allow the action |
388 | to be executed on the "controller/method" URL, or, in this case, |
389 | "site/test", instead of at the root site URL, like "Global". It's not |
390 | actually necessary to set the template value, since by default TT will |
391 | attempt to render a template that follows the naming pattern |
392 | "controller/method.tt", and we're following that pattern here, but in |
393 | other situations you will need to specify the template (such as if |
394 | you've "forwarded" to the method, or if it doesn't follow the default |
395 | naming convention). We've also put the variable "name" into the stash, |
396 | for use in the template. |
d442cc9f |
397 | |
3533daff |
398 | Make a subdirectory "site" in the "root" directory. Copy the hello.tt |
d0496197 |
399 | file into the directory as C<root/site/test.tt>, or create a new |
400 | template file at that location. Include a line like: |
d442cc9f |
401 | |
d0496197 |
402 | <p>Hello, [% username %]!</p> |
d442cc9f |
403 | |
3533daff |
404 | Bring up or restart the server. Notice in the server output that |
405 | C</site/test> is listed in the Loaded Path actions. Go to |
d0496197 |
406 | L<http://localhost:3000/site/test> |
d442cc9f |
407 | |
3533daff |
408 | You should see your test.tt file displayed, including the name "John" |
409 | that you set in the controller. |
d442cc9f |
410 | |
d442cc9f |
411 | |
3533daff |
412 | =head1 AUTHORS |
d442cc9f |
413 | |
3533daff |
414 | Gerda Shank, C<gerda.shank@gmail.com> |
d442cc9f |
415 | Kennedy Clark, C<hkclark@gmail.com> |
416 | |
417 | Please report any errors, issues or suggestions to the author. The |
418 | most recent version of the Catalyst Tutorial can be found at |
d712b826 |
419 | L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>. |
d442cc9f |
420 | |
45c7830f |
421 | Copyright 2006-2008, Kennedy Clark & Gerda Shank, under Creative Commons License |
d442cc9f |
422 | (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>). |