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