1HTML::Mason::SubclassinUgs(e3r)Contributed Perl DocumentHaTtMiLo:n:Mason::Subclassing(3)
2
3
4
6 HTML::Mason::Subclassing - Documentation on Subclassing Internal Mason
7 classes
8
10 This is the deep voodoo guide, for folks who want to create their own
11 custom subclasses for parts of Mason, such as the Request or Interp
12 objects.
13
15 A number of modules in Mason are subclasses of "Class::Container".
16 This module was originally part of the Mason core as "HTML::Mason::Con‐
17 tainer", but Ken Williams decided to release it separately on CPAN.
18
19 It was created to encapsulate some common behaviors for Mason objects
20 such as parameter validation and the creation of "contained" objects.
21
22 Basically, any Mason object which takes parameters to its constructor
23 must inherit from this module. Of course, since all of the classes
24 that you might consider subclassing already inherit from "Class::Con‐
25 tainer", you won't need to inherit from it directly. However, you may
26 need to use some of its methods.
27
28 So before you go further we highly recommend familiarizing yourself
29 with "Class::Container" and its methods. Also feel free to look at
30 some of the Mason core modules to see how "Class::Container" is used
31 within Mason itself.
32
34 The following classes have been designed with subclassing in mind:
35
36 * HTML::Mason::Request
37 This object is your old friend $m. The request contains informa‐
38 tion about the current request context, and provides methods for
39 calling other components.
40
41 * HTML::Mason::Resolver
42 The resolver's job is to translate a component paths into an actual
43 component. Mason comes with a single Resolver subclass,
44 "HTML::Mason::Resolver::File", which is used to translate component
45 paths into filesystem paths.
46
47 * HTML::Mason::ComponentSource
48 An object of this class represents a component's source. These
49 objects are instantiated by the resolver when it finds a component
50 matching a given path.
51
52 * HTML::Mason::Lexer
53 The lexer is responsible for parsing a component. Creating a new
54 lexer would allow you to change Mason's component syntax.
55
56 * HTML::Mason::Compiler
57 The compiler takes the parsed chunks from the lexer and gives them
58 meaning. The default compiler, "HTML::Mason::Compiler::ToObject",
59 turns a Mason component into a Mason "object file", which contains
60 actual Perl code.
61
62 * HTML::Mason::ApacheHandler
63 The ApacheHandler class is the bridge between the mod_perl world
64 and Mason, primarily Mason's Interp class.
65
66 It also provides its own "HTML::Mason::Request" and
67 "HTML::Resolver::File" subclasses which implement some mod_perl
68 specific behaviors and features.
69
70 * HTML::Mason::Interp
71 The Interp is the core of Mason, and is primarily responsible for
72 making all the other objects do their jobs.
73
75 If you choose to override the constructor, which is always "new" with
76 Mason objects, that you make sure to call the superclass's constructor
77 and that you use the object returned by it. A good boilerplate for an
78 overridden constructor looks something like this:
79
80 sub new
81 {
82 my $class = shift;
83
84 my $self = $class->SUPER::new(@_);
85
86 $self->_do_some_init;
87
88 return $self;
89 }
90
92 What to Subclass?
93
94 One important thing to know about this class is that it is actually
95 several classes. The first, "HTML::Mason::Request", is used when
96 ApacheHandler is not loaded. The other,
97 "HTML::Mason::Request::ApacheHandler", is loaded by ApacheHandler and
98 used to provide some mod_perl specific features. Similar, the CGIHan‐
99 dler class provides its own request subclass,
100 "HTML::Mason::Request::CGIHandler".
101
102 It is impossible to know which one of these to subclass at compile
103 time, since it is possible that your subclass will be loaded before
104 either ApacheHandler or CGIHandler.
105
106 To handle this, simply call the "alter_superclass()" method in your
107 constructor, like this:
108
109 sub new
110 {
111 my $class = shift;
112
113 $class->alter_superclass( $HTML::Mason::ApacheHandler::VERSION ?
114 'HTML::Mason::Request::ApacheHandler' :
115 $HTML::Mason::CGIHandler::VERSION ?
116 'HTML::Mason::Request::CGI' :
117 'HTML::Mason::Request' );
118
119 my $self = $class->SUPER::new(@_);
120
121 ...
122
123 return $self;
124 }
125
126 It is quite important that you do this as these handler-specific sub‐
127 classes provide important functionality. The "alter_superclass()"
128 method is implemented in the "HTML::Mason::Request" base class, and
129 will do the right thing even in cases of multiple inheritance. It also
130 cooperates with "Class::Container" to make sure that it sees changes to
131 the inheritance hierarchy.
132
133 The exec() method
134
135 The "exec" method is called in order to execute a request, and is the
136 method that you are most likely to want to override.
137
138 However, if you do override it we suggest that you make sure to call
139 the parent class's "exec" method to implement the actual component exe‐
140 cution and there is no need for you to re-implement them.
141
142 Since the "exec()" method is scalar/list context-sensitive, your "exec"
143 method will need to preserve that. Here is a boilerplate:
144
145 sub exec
146 {
147 my $self = shift;
148
149 ... # do something cool
150
151 my @r;
152 if (wantarray)
153 {
154 @r = $self->SUPER::exec(@_);
155 }
156 else
157 {
158 $r[0] = $self->SUPER::exec(@_);
159 }
160
161 ... # maybe do some cleanup
162
163 return wantarray ? @r : $r[0];
164 }
165
166 Subrequests
167
168 Your custom request class will also be used to implement subrequests,
169 which are implemented by calling "exec" just like any other method. If
170 you only want to do certain things in "exec" for the first request, you
171 can simply check the value of "$self->is_subrequest".
172
173 Examples
174
175 See the "MasonX::Request::WithApacheSession" module on CPAN.
176
178 The resolver takes a component path and figures out what component that
179 path corresponds to.
180
181 All resolver classes must implement two methods, "get_info" and
182 "glob_path". The first takes a component path and returns a new
183 "HTML::Mason::ComponentSource" object. This object contains informa‐
184 tion about the component, such as its last modified time and its
185 source. See the "HTML::Mason::ComponentSource" documentation for more
186 details.
187
188 You may choose to provide your own ComponentSource subclass as well, if
189 your resolver implementation can take advantage of it.
190
191 The "glob_path" method is responsible for translating a component path
192 like /foo/*/bar into a list of component paths that match that glob
193 pattern.
194
196 The rationale for providing your own lexer would be to extend or
197 replace Mason's syntax.
198
199 The lexer is called by the compiler via its "lex" method. The argu‐
200 ments it receives are the component name, source, and the compiler
201 object. See the Compiler class documentation for details on what meth‐
202 ods the lexer can call.
203
205 See the Compiler class documentation for details on what methods a sub‐
206 class of this class needs to provide.
207
208 If you simply want to tweak Mason's existing behavior, you will proba‐
209 bly want to subclass "HTML::Mason::Compiler::ToObject", which is the
210 default Compiler class. For example, if you wanted to do something
211 like make attributes dynamic, you could override the "_flags_or_attr()"
212 method in ToObject.
213
214 If you want to drastically change the behavior, you can subclass
215 "HTML::Mason::Compiler" instead. An example of this would be creating
216 a compiler that generates "EmbPerl" or "Apache::ASP" as output.
217
219 The methods that you are most likely to want to subclass are documented
220 in the "ApacheHandler class" documentation.
221
222 Providing an ApacheHandler subclass gives you a chance to do your own
223 client parameter parsing, as well as the capability of providing a dif‐
224 ferent way of handling requests.
225
227 Like the ApacheHandler, you could subclass this module in order to pro‐
228 vide your own argument processing or to step in and provide a different
229 way to handle requests.
230
232 When using your custom subclasses, we recommend that you take advantage
233 of Mason's ability to construct subclassed object on the fly.
234
235 For example, if you're subclassed the Interp object, you can still let
236 the ApacheHandler object create the Interp object for you, as long as
237 you give it the appropriate interp_class parameter. This is important
238 because Mason may internally set up certain defaults for contained
239 objects. For example, the ApacheHandler, by default, will tell the
240 Interp object to use the "HTML::Mason::Request::ApacheHandler" Request
241 subclass. If you create an Interp object manually and you want to use
242 that Interp object with ApacheHandler, you'll have to specify the same
243 Request class.
244
245 For example:
246
247 my $interp =
248 My::Interp->new
249 ( request_class => 'HTML::Mason::Request::ApacheHandler',
250 my_new_interp_param => 42,
251 );
252
253 my $ah = HTML::Mason::ApacheHandler->new( interp => $interp );
254
255 It is far easier to simply do this:
256
257 my $ah =
258 HTML::Mason::ApacheHandler->new
259 ( interp_class => 'My::Interp',
260 my_new_interp_param => 42,
261 );
262
263 Your new parameter, "my_new_interp_param", will still be passed to the
264 "My::Interp" constructor, but this also gives ApacheHandler a chance to
265 set various parameters for the Interp object. Of course, you can still
266 override these defaults explicitly:
267
268 my $ah =
269 HTML::Mason::ApacheHandler->new
270 ( interp_class => 'My::Interp',
271 resolver_class => 'My::Resolver'.
272 my_new_interp_param => 42,
273 );
274
275 If you need access to the interp object's methods directly, it will be
276 always be available via "$ah->interp".
277
278
279
280perl v5.8.8 2007-04-17 HTML::Mason::Subclassing(3)