Catalyst Advent - Day 22 - Action Types
Introduction
A Catalyst application is driven by one or more Controller modules. There are a number of ways that Catalyst can decide which of the methods in your controller modules it should call. Controller methods are also called actions, because they determine how your catalyst application should (re-)act to any given URL. When the application is started up, catalyst looks at all your actions, and decides which URLs they map to.
Type attributes
Each action is a normal method in your controller, except that it has an attribute attached. These can be one of several types.
Assume our Controller module starts with the following package declaration:
package MyApp::Controller::Buckets;
and we are running our application on localhost, port 3000 (the test server default).
- Path
-
A Path attribute also takes an argument, this can be either a relative or an absolute path. A relative path will be relative to the controller namespace, an absolute path will represent an exact matching URL.
sub my_handles : Path('handles') { .. }
becomes
http://localhost:3000/buckets/handles
and
sub my_handles : Path('/handles') { .. }
becomes
http://localhost:3000/handles
- Local
-
When using a Local attribute, no parameters are needed, instead, the name of the action is matched in the URL. The namespaces created by the name of the controller package is always part of the URL.
sub my_handles : Local { .. }
becomes
http://localhost:3000/buckets/my_handles
- Global
-
A Global attribute is similar to a Local attribute, except that the namespace of the controller is ignored, and matching starts at root.
sub my_handles : Global { .. }
becomes
http://localhost:3000/my_handles
- Regex
-
By now you should have figured that a Regex attribute is just what it sounds like. This one takes a regular expression, and matches starting from root. These differ from the rest as they can match multiple URLs.
sub my_handles : Regex('^handles') { .. }
matches
http://localhost:3000/handles
and
http://localhost:3000/handles_and_other_parts
etc.
- LocalRegex
-
A LocalRegex is similar to a Regex, except it only matches below the current controller namespace.
sub my_handles : LocalRegex(^handles') { .. }
matches
http://localhost:3000/buckets/handles
and
http://localhost:3000/buckets/handles_and_other_parts
etc.
- Private
-
Last but not least, there is the Private attribute, which allows you to create your own internal actions, which can be forwarded to, but won't be matched as URLs.
sub my_handles : Private { .. }
becomes nothing at all..
Catalyst also predefines some special Private actions, which you can override, these are:
- default
-
The default action will be called, if no other matching action is found. If you don't have one of these in your namespace, or any sub part of your namespace, you'll get an error page instead. If you want to find out where it was the user was trying to go, you can look in the request object using
$c->req->path
.sub default : Private { .. }
works for all unknown URLs, in this controller namespace, or every one if put directly into MyApp.pm.
- index
-
The index action is called when someone tries to visit the exact namespace of your controller. If index, default and matching Path actions are defined, then index will be used instead of default and Path.
sub index : Private { .. }
becomes
http://localhost:3000/buckets
- begin
-
The begin action is called at the beginning of every request involving this namespace directly, before other matching actions are called. It can be used to set up variables/data for this particular part of your app. A single begin action is called, its always the one most relevant to the current namespace.
sub begin : Private { .. }
is called once when
http://localhost:3000/bucket/(anything)?
is visited.
- end
-
Like begin, this action is always called for the namespace it is in, after every other action has finished. It is commonly used to forward processing to the View component. A single end action is called, its always the one most relevant to the current namespace.
sub end : Private { .. }
is called once after any actions when
http://localhost:3000/bucket/(anything)?
is visited.
- auto
-
Lastly, the auto action is magic in that every auto action in the chain of paths up to and including the ending namespace, will be called. (In contrast, only one of the begin/end/default actions will be called, the relevant one).
package MyApp.pm; sub auto : Private { .. }
and
sub auto : Private { .. }
will both be called when visiting
http://localhost:3000/bucket/(anything)?
A word of warning
Due to possible namespace conflicts with Plugins, it is advised to only put the pre-defined Private actions in your main MyApp.pm file, all others should go in a Controller module.