svk-commitBGCdt.tmp
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / WritingPlugins.pod
1 =head1 NAME
2
3 Catalyst::Manual::WritingPlugins - An introduction to writing plugins
4 with L<NEXT>.
5
6 =head1 DESCRIPTION
7
8 Writing an integrated plugin for L<Catalyst> using L<NEXT>.
9
10 =head1 WHY PLUGINS?
11
12 A Catalyst plugin is an integrated part of your application. By writing
13 plugins you can, for example, perform processing actions automatically,
14 instead of having to C<forward> to a processing method every time you
15 need it.
16
17 =head1 WHAT'S NEXT?
18
19 L<NEXT> is used to re-dispatch a method call as if the calling method
20 doesn't exist at all. In other words: If the class you're inheriting
21 from defines a method, and you're overloading that method in your own
22 class, NEXT gives you the possibility to call that overloaded method.
23
24 This technique is the usual way to plug a module into Catalyst.
25
26 =head1 INTEGRATING YOUR PLUGIN
27
28 You can use L<NEXT> for your plugin by overloading certain methods which
29 are called by Catalyst during a request.
30
31 =head2 The request life-cycle
32
33 Catalyst creates a context object (C<$context> or, more usually, its
34 alias C<$c>) on every request, which is passed to all the handlers that
35 are called from preparation to finalization.
36
37 For a complete list of the methods called during a request, see
38 L<Catalyst::Manual::Internals>. The request can be split up in three
39 main stages:
40
41 =over 4
42
43 =item preparation
44
45 When the C<prepare> handler is called, it initializes the request
46 object, connections, headers, and everything else that needs to be
47 prepared. C<prepare> itself calls other methods to delegate these tasks.
48 After this method has run, everything concerning the request is in
49 place.
50
51 =item dispatch
52
53 The dispatching phase is where the black magic happens. The C<dispatch>
54 handler decides which actions have to be called for this request.
55
56 =item finalization
57
58 Catalyst uses the C<finalize> method to prepare the response to give to
59 the client. It makes decisions according to your C<response> (e.g. where
60 you want to redirect the user to). After this method, the response is
61 ready and waiting for you to do something with it--usually, hand it off
62 to your View class.
63
64 =back
65
66 =head2 What Plugins look like
67
68 There's nothing special about a plugin except its name. A module named
69 C<Catalyst::Plugin::MyPlugin> will be loaded by Catalyst if you specify it
70 in your application class, e.g.:
71
72     # your plugin
73     package Catalyst::Plugin::MyPlugin;
74     use warnings;
75     use strict;
76     ...
77
78     # MyApp.pm, your application class
79     use Catalyst qw/-Debug MyPlugin/;
80
81 This does nothing but load your module. We'll now see how to overload stages of the request cycle, and provide accessors.
82
83 =head2 Calling methods from your Plugin
84
85 Methods that do not overload a handler are available directly in the
86 C<$c> context object; they don't need to be qualified with namespaces,
87 and you don't need to C<use> them.
88
89     package Catalyst::Plugin::Foobar;
90     use strict;
91     sub foo { return 'bar'; }
92
93     # anywhere else in your Catalyst application:
94
95     $c->foo(); # will return 'bar'
96
97 That's it.
98
99 =head2 Overloading - Plugging into Catalyst
100
101 If you don't just want to provide methods, but want to actually plug
102 your module into the request cycle, you have to overload the handler
103 that suits your needs.
104
105 Every handler gets the context object passed as its first argument. Pass
106 the rest of the arguments to the next handler in row by calling it via
107
108     $c->NEXT::handler-name( @_ );
109
110 if you already C<shift>ed it out of C<@_>. Remember to C<use> C<NEXT>.
111
112 =head2 Storage and Configuration
113
114 Some Plugins use their accessor names as a storage point, e.g.
115
116   sub my_accessor {
117     my $c = shift;
118     $c->{my_accessor} = ..
119
120 but it is more safe and clear to put your data in your configuration
121 hash:
122
123     $c->config->{my_plugin}{ name } = $value;
124
125 If you need to maintain data for more than one request, you should
126 store it in a session.
127
128 =head1 EXAMPLE
129
130 Here's a simple example Plugin that shows how to overload C<prepare> 
131 to add a unique ID to every request:
132
133     package Catalyst::Plugin::RequestUUID;
134
135     use warnings;
136     use strict;
137
138     use Catalyst::Request;
139     use Data::UUID;
140     use NEXT;    
141
142     our $VERSION = 0.01;
143
144     {   # create a uuid accessor
145         package Catalyst::Request;
146         __PACKAGE__->mk_accessors('uuid');
147     }
148
149     sub prepare {
150       my $class = shift;
151
152       # Turns the engine-specific request into a Catalyst context .
153       my $c = $class->NEXT::prepare( @_ );
154
155       $c->request->uuid( Data::UUID->new->create_str );
156       $c->log->debug( 'Request UUID "'. $c->request->uuid .'"' );
157
158       return $c;
159     }
160
161     1;
162
163 Let's just break it down into pieces:
164
165     package Catalyst::Plugin::RequestUUID;
166
167 The package name has to start with C<Catalyst::Plugin::> to make sure you
168 can load your plugin by simply specifying
169
170     use Catalyst qw/RequestUUID/;
171
172 in the application class. L<warnings> and L<strict> are recommended for
173 all Perl applications.
174
175     use NEXT;
176     use Data::UUID;
177     our $VERSION = 0.01;
178
179 NEXT must be explicitly C<use>d. L<Data::UUID> generates our unique
180 ID. The C<$VERSION> gets set because it's a) a good habit and b)
181 L<ExtUtils::ModuleMaker> likes it.
182
183     sub prepare {
184
185 These methods are called without attributes (Private, Local, etc.).
186
187     my $c = shift;
188
189 We get the context object for this request as the first argument. 
190
191 B<Hint!>:Be sure you shift the context object out of C<@_> in this. If
192 you just do a
193
194   my ( $c ) = @_;
195
196 it remains there, and you may run into problems if you're not aware of
197 what you pass to the handler you've overloaded. If you take a look at
198
199     $c = $c->NEXT::prepare( @_ );
200
201 you see you would pass the context twice here if you don't shift it out
202 of your parameter list.
203
204 This line is the main part of the plugin procedure. We call the
205 overloaded C<prepare> method and pass along the parameters we got. We
206 also overwrite the context object C<$c> with the one returned by the
207 called method returns. We'll return our modified context object at the
208 end.
209
210 Note that that if we modify C<$c> before this line, we also modify it
211 before the original (overloaded) C<prepare> is run. If we modify it
212 after, we modify an already prepared context. And, of course, it's no
213 problem to do both, if you need to. Another example of working on the
214 context before calling the actual handler would be setting header
215 information before C<finalize> does its job.
216
217     $c->req->{req_uuid} = Data::UUID->new->create_str;
218
219 This line creates a new L<Data::UUID> object and calls the C<create_str>
220 method. The value is saved in our request, under the key C<req_uuid>. We
221 can use that to access it in future in our application.
222
223     $c->log->debug( 'Request UUID "'. $c->req->{req_uuid} .'"' );
224
225 This sends our UUID to the C<debug> log.
226
227 The final line
228
229     return $c;
230
231 passes our modified context object back to whoever has called us. This
232 could be Catalyst itself, or the overloaded handler of another plugin.
233
234 =head1 SEE ALSO
235
236 L<Catalyst>, L<NEXT>, L<ExtUtils::ModuleMaker>, L<Catalyst::Manual::Plugins>,
237 L<Catalyst::Manual::Internals>.
238
239 =head1 THANKS TO
240
241 Sebastian Riedel and his team of Catalyst developers as well as all the
242 helpful people in #catalyst.
243
244 =head1 COPYRIGHT
245
246 This program is free software, you can redistribute it and/or modify it
247 under the same terms as Perl itself.
248
249 =head1 AUTHOR
250
251 S<Robert Sedlacek, C<phaylon@dunkelheit.at>> with a lot of help from the
252 people on #catalyst.
253
254 =cut