Cataly...roller(3pm)
π Catalyst::Controller β the controller base class, bestie π
okay so this is Catalyst::Controller, the base class every Catalyst controller inherits from. It lives in the User Contributed Perl Documentation section, section 3pm, and yes she's iconic for a reason. Let's get into it. π
β¨ SYNOPSIS β¨
package MyApp::Controller::Search
use base qw/Catalyst::Controller/;
sub foo : Local {
my ($self,$c,@args) = @_;
...
} # Dispatches to /search/foo
see how cute that is? You write a sub, slap an attribute on it, and boom β that's an action now. π
πΈ DESCRIPTION πΈ
Controllers are literally where the actions live in the Catalyst framework. Every action is just a function with an attribute that tells Catalyst what kind of action it is. Wanna know how Catalyst actually dispatches to those actions? Go read Catalyst::Dispatcher. iykyk. π¦
π CONFIGURATION π
Just like every other Catalyst::Component, controllers get a config hash, and you can reach it from inside your actions with $self->config. Some of these keys are actually used by the Catalyst framework itself, so pay attention bestie:
π namespace
This sets the internal namespace the controller gets bound to. If you don't set it, the controller just gets bound to the URI version of its own name. So like, controller 'MyApp::Controller::Foo::Bar' ends up bound to 'foo/bar'. The default Root controller is the classic example of setting namespace to '' β the null string, yes, empty, nothing, void. π
π path
This one sets 'path_prefix', which is described down below. Simple as that.
π action
This lets you set the attributes that the dispatcher builds actions out of. Which meansβ¦ you can do 'rails style routes' β¨, or override some of the attribute definitions on actions that got composed from Roles. You can set args globally (for every action in the controller) and specifically (for just one action). Both! At the same time! π
__PACKAGE__->config(
action => {
'*' => { Chained => 'base', Args => 0 },
base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
},
);
So in that example up there, every single sub in the package becomes a Chain endpoint whose URI matches the sub name, and they're all chained to the sub called "base". Which means dispatching to "/example" would call the "base" method first, and then the "example" method. Cute, right? π«Ά
π action_args
This one lets you set constructor arguments on your actions. Same deal as before β global and specific, both available. It's especially handy when you're using "ActionRole"s (Catalyst::Controller::ActionRole) and custom "ActionClass"es.
__PACKAGE__->config(
action_args => {
'*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
'specific_action' => { customarg => 'arg1' },
},
);
And in that case, the action class tied to "specific_action" gets handed these arguments β on top of the normal action constructor arguments β when it gets instantiated:
(globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
π METHODS π
π BUILDARGS ($app, @args)
Straight from Catalyst::Component::ApplicationAttribute. It stashes the application instance as $self->_application. That's the whole job. She's efficient.
π $self->action_for($action_name)
Hands you back the Catalyst::Action object (if there is one) for a given action in this controller, or relative to it. You can point at actions in controllers nested under the current controller's namespace, or in controllers that are 'up' from the current controller's namespace. Like so:
package MyApp::Controller::One::Two;
use base 'Catalyst::Controller';
sub foo :Local {
my ($self, $c) = @_;
$self->action_for('foo'); # action 'foo' in Controller 'One::Two'
$self->action_for('three/bar'); # action 'bar' in Controller 'One::Two::Three'
$self->action_for('../boo'); # action 'boo' in Controller 'One'
}
Heads up bestie: this returns 'undef' if there's no action matching the name you asked for (after any path normalization), so check for that whenever you need to. No cap. π
π $self->action_namespace($c)
Returns the private namespace for actions in this component. By default it comes from the controller name β so MyApp::Controller::Foo::Bar becomes "foo/bar" β or you can override it with the "namespace" config key. Slay. β¨
π $self->path_prefix($c)
Returns the default path prefix for :PathPrefix, :Local and relative :Path actions in this component. Defaults to the action_namespace, or you can override it with the "path" config key.
π $self->register_actions($c)
Finds every applicable action for this component, builds Catalyst::Action objects for them (using $self->create_action), and registers them with $c->dispatcher. Go get 'em. π₯
π $self->get_action_methods()
Returns a list of Moose::Meta::Method objects that do the MooseX::MethodAttributes::Role::Meta::Method role β aka the whole set of action methods for this package. π
π $self->register_action_methods($c, @methods)
Creates action objects for a set of action methods using " create_action ", then registers them with the dispatcher.
π $self->action_class(%args)
Used when a controller is creating an action, to figure out the correct base action class to use. It's giving matchmaker energy.
π $self->create_action(%args)
Called with a hash of data to be used for constructing a new Catalyst::Action (or whatever appropriate sub/alternative class) object. πΈ
π $self->gather_action_roles(%action_args)
Gathers up the list of roles to apply to an action with the given %action_args.
π $self->gather_default_action_roles(%action_args)
Returns a list of action roles to apply based on core, builtin rules. Currently the only role applied this way is the Catalyst::ActionRole::HTTPMethods role. That's it, that's the list. π¦
π $self->_application
π $self->_app
Returns the application instance stored by new(). Two names, same icon. π
β¨ ACTION SUBROUTINE ATTRIBUTES β¨
Please see Catalyst::Manual::Intro for more details
Okay so bestie, think of action attributes as lil metadata stickers you slap on an action β kinda like annotations in other languages you might've heard of. Catalyst usually uses them to tell the dispatcher how to see your action and when it should run when a request comes in. They can do other stuff too. Here's the summary, but fr go check the linked manual page for extra help.
π Global
sub homepage :Global { ... }
A global action defined in any controller always runs relative to your root. So the above is the same as:
sub myaction :Path("/homepage") { ... }
π§ Absolute
Status: Deprecated alias to Global.
π Local
Alias to Path("$action_name"). The following two actions are the same:
sub myaction :Local { ... }
sub myaction :Path('myaction') { ... }
π Relative
Status: Deprecated alias to Local
π£οΈ Path
Handle various types of paths:
package MyApp::Controller::Baz {
...
sub myaction1 :Path { ... } # -> /baz
sub myaction2 :Path('foo') { ... } # -> /baz/foo
sub myaction2 :Path('/bar') { ... } # -> /bar
}
This is a general toolbox for attaching your action to a given path.
π§© Regex
π§© Regexp
Status: Deprecated. Use Chained methods or other techniques. If you really depend on this, install the standalone Catalyst::DispatchType::Regex distribution.
A global way to match a given regular expression in the incoming request path.
π§© LocalRegex
π§© LocalRegexp
Status: Deprecated. Use Chained methods or other techniques. If you really depend on this, install the standalone Catalyst::DispatchType::Regex distribution.
Like Regex but scoped under the namespace of the containing controller
βοΈ Chained
βοΈ ChainedParent
βοΈ PathPrefix
βοΈ PathPart
βοΈ CaptureArgs
Allowed values for CaptureArgs is a single integer (CaptureArgs(2), meaning two allowed) or you can declare a Moose, MooseX::Types or Type::Tiny named constraint such as CaptureArgs(Int,Str) would require two args with the first being a Integer and the second a string. You may declare your own custom type constraints and import them into the controller namespace:
package MyApp::Controller::Root;
use Moose;
use MooseX::MethodAttributes;
use MyApp::Types qw/Int/;
extends 'Catalyst::Controller';
sub chain_base :Chained(/) CaptureArgs(1) { }
sub any_priority_chain :Chained(chain_base) PathPart('') Args(1) { }
sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
See Catalyst::RouteMatching for more.
Please see Catalyst::DispatchType::Chained for more.
π ActionClass
Set the base class for the action, defaults to Catalyst::Action. It is now preferred to use Does.
π MyAction
Set the ActionClass using a custom Action in your project namespace.
The following is exactly the same:
sub foo_action1 : Local ActionClass('+MyApp::Action::Bar') { ... }
sub foo_action2 : Local MyAction('Bar') { ... }
π Does
package MyApp::Controller::Zoo;
sub foo : Local Does('Buzz') { ... } # Catalyst::ActionRole::
sub bar : Local Does('~Buzz') { ... } # MyApp::ActionRole::Buzz
sub baz : Local Does('+MyApp::ActionRole::Buzz') { ... }
π¬ GET, POST, PUT, DELETE, OPTION, HEAD, PATCH, Method('...')
Sets the given action path to match the specified HTTP method, or via one of the broadly accepted methods of overriding the 'true' method (see Catalyst::ActionRole::HTTPMethods).
π¦ Args
When used with Path indicates the number of arguments expected in the path. However if no Args value is set, assumed to 'slurp' all remaining path pars under this namespace.
Allowed values for Args is a single integer (Args(2), meaning two allowed) or you can declare a Moose, MooseX::Types or Type::Tiny named constraint such as Args(Int,Str) would require two args with the first being a Integer and the second a string. You may declare your own custom type constraints and import them into the controller namespace:
package MyApp::Controller::Root;
use Moose;
use MooseX::MethodAttributes;
use MyApp::Types qw/Tuple Int Str StrMatch UserId/;
extends 'Catalyst::Controller';
sub user :Local Args(UserId) {
my ($self, $c, $int) = @_;
}
sub an_int :Local Args(Int) {
my ($self, $c, $int) = @_;
}
sub many_ints :Local Args(ArrayRef[Int]) {
my ($self, $c, @ints) = @_;
}
sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
my ($self, $c, $int) = @_;
}
If you choose not to use imported type constraints (like Type::Tiny, or MooseX::Types) you may use Moose 'stringy' types however just like when you use these types in your declared attributes you must quote them:
sub my_moose_type :Local Args('Int') { ... }
If you use 'reference' type constraints (such as ArrayRef[Int]) that have an unknown number of allowed matches, we set this the same way Args is. Please keep in mind that actions with an undetermined number of args match at lower precedence than those with a fixed number. You may use reference types such as Tuple from Types::Standard that allows you to fix the number of allowed args. For example Args(Tuple[Int,Int]) would be determined to be two args (or really the same as Args(Int,Int).) You may find this useful for creating custom subtypes with complex matching rules that you wish to reuse over many actions.
See Catalyst::RouteMatching for more.
Note: It is highly recommended to use Type::Tiny for your type constraints over other options. Type::Tiny exposed a better meta data interface which allows us to do more and better types of introspection driving tests and debugging.
π½οΈ Consumes('...')
Matches the current action against the content-type of the request. Typically this is used when the request is a POST or PUT and you want to restrict the submitted content type. For example, you might have an HTML form that either returns classic url encoded form data, or JSON when Javascript is enabled. In this case you may wish to match either incoming type to one of two different actions, for properly processing.
Examples:
sub is_json : Chained('start') Consumes('application/json') { ... }
sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
sub is_multipart : Chained('start') Consumes('multipart/form-data') { ... }
To reduce boilerplate, we include the following content type shortcuts:
Examples
sub is_json : Chained('start') Consume(JSON) { ... }
sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
sub is_multipart : Chained('start') Consumes(Multipart) { ... }
You may specify more than one match:
sub is_more_than_one
: Chained('start')
: Consumes('application/x-www-form-urlencoded')
: Consumes('multipart/form-data')
sub is_more_than_one
: Chained('start')
: Consumes(UrlEncoded)
: Consumes(Multipart)
Since it is a common case the shortcut HTMLForm matches both 'application/x-www-form-urlencoded' and 'multipart/form-data'. Here's the full list of available shortcuts:
JSON => 'application/json',
JS => 'application/javascript',
PERL => 'application/perl',
HTML => 'text/html',
XML => 'text/XML',
Plain => 'text/plain',
UrlEncoded => 'application/x-www-form-urlencoded',
Multipart => 'multipart/form-data',
HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
Please keep in mind that when dispatching, Catalyst will match the first most relevant case, so if you use the Consumes attribute, you should place your most accurate matches early in the Chain, and your 'catchall' actions last.
See Catalyst::ActionRole::ConsumesContent for more.
π Scheme(...)
Allows you to specify a URI scheme for the action or action chain. For example you can required that a given path be https or that it is a websocket endpoint ws or wss. For an action chain you may currently only have one defined Scheme.
package MyApp::Controller::Root;
use base 'Catalyst::Controller';
sub is_http :Path(scheme) Scheme(http) Args(0) {
my ($self, $c) = @_;
$c->response->body("is_http");
}
sub is_https :Path(scheme) Scheme(https) Args(0) {
my ($self, $c) = @_;
$c->response->body("is_https");
}
In the above example http://localhost/root/scheme would match the first action (is_http) but https://localhost/root/scheme would match the second.
As an added benefit, if an action or action chain defines a Scheme, when using $c->uri_for the scheme of the generated URL will use what you define in the action or action chain (the current behavior is to set the scheme based on the current incoming request). This makes it easier to use uri_for on websites where some paths are secure and others are not. You may also use this to other schemes like websockets.
See Catalyst::ActionRole::Scheme for more.
β¨ OPTIONAL METHODS β¨
π οΈ _parse_[$name]_attr
Allows you to customize parsing of subroutine attributes.
sub myaction1 :Path TwoArgs { ... }
sub _parse_TwoArgs_attr {
my ( $self, $c, $name, $value ) = @_;
# $self -> controller instance
#
return(Args => 2);
}
Please note that this feature does not let you actually assign new functions to actions via subroutine attributes, but is really more for creating useful aliases to existing core and extended attributes, and transforms based on existing information (like from configuration). Code for actually doing something meaningful with the subroutine attributes will be located in the Catalyst::Action classes (or your subclasses), Catalyst::Dispatcher and in subclasses of Catalyst::DispatchType. Remember these methods only get called basically once when the application is starting, not per request!
π AUTHORS
Catalyst Contributors, see Catalyst.pm
π COPYRIGHT
This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself.
π That's the whole page, bestie! Perl v5.40.0, 2024-11-15, Cataly...roller(3pm) β you ate and left no crumbs. π«Ά
π¦ where this page comes from
- debian trixie: libcatalyst-perl 5.90132-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libcatalyst-perl 5.90132-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libcatalyst-perl 5.90132-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms