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