Catalyst::Manual::CatalystAndMoose - How Catalyst 5.8+ and Moose relate
-
=head1 DESCRIPTION
-Since version 5.8 the core of Catalyst is based on L<Moose>. Although
-the developers went through great lengths to allow for a seamless
-transition, there are still a few things to keep in mind when trying
+Since version 5.8, the core of Catalyst is based on L<Moose>. Although
+the developers went through great lengths to allow for a seamless
+transition, there are still a few things to keep in mind when trying
to exploit the power of L<Moose> in your Catalyst application.
-This document provides you with a short overview of common caveats and
-best practices to use L<Moose>-based classes within Catalyst.
-
+This document provides you with a short overview of common caveats and
+best practices for using L<Moose>-based classes within Catalyst.
=head1 THE CONTEXT CLASS
A Moose-ified version of the context class should look like this:
package MyApp;
-
use Moose;
use namespace::autoclean;
use Catalyst (
# your roles and plugins
);
-
+ extends 'Catalyst';
+
+ # If you want to use method modifiers to adjust the setup process, (e.g. setup_finalize)
+ # they must be here, before the call to setup (advanced users only)
+
$app->config( name => 'MyApp' );
$app->setup;
-
- # method modifiers must be created after setup because otherwise they will
+
+ # method modifiers generally must be created after setup because otherwise they will
# conflict with plugin overrides
-
- after 'finalize' => sub{
+
+ after 'finalize' => sub {
my $c = shift;
$c->log->info( 'done!' );
}
-You should also be aware, that roles in C<< $c-E<gt>setup >> are applied
-after the last plugin with all the benefits of using a single
-C<< with() >> statement in an ordinary L<Moose> class.
+You should also be aware that roles in C<< $c-E<gt>setup >> are applied
+after the last plugin with all the benefits of using a single
+L<with()|Moose/"with (@roles)"> statement in an ordinary L<Moose> class.
-Your class is automatically made immutable at the end of the current file.
+Your class is automatically made immutable at the end of the current file.
-CAVEAT: Using roles in C<< $c-E<gt>setup >> was implemented in Catalyst
+CAVEAT: Using roles in C<< $c-E<gt>setup >> was implemented in Catalyst
version 5.80004. In prior versions you might get away with
after 'setup_plugins' => sub{ with(
# your roles
)};
-
+
$app->setup(
# your plugins
);
-but this is discouraged and you should upgrade to 5.80004 anyway,
-because it fixes a few important regression against 5.71
+but this is discouraged and you should upgrade to 5.80004 anyway,
+because it fixes a few important regressions against 5.71
CAVEAT: Using roles in C<< $c-E<gt>setup >> will not currently allow
you to pass parameters to roles, or perform conflict resolution.
Conflict detection still works as expected.
-
=head2 ACCESSORS
-Most of the request-specific attributes like C<$c-E<gt>stash>,
-C<$c-E<gt>request> and C<$c-E<gt>response> have been converted to
-L<Moose> attributes but without type constraints, attribute helpers or
-builder methods. This ensures that Catalyst 5.8 is fully backwards
-compatible to applications using the published API of Catalyst 5.7 but
-slightly limits the gains that could be had by wielding the full power
+Most of the request-specific attributes like C<$c-E<gt>stash>,
+C<$c-E<gt>request> and C<$c-E<gt>response> have been converted to
+L<Moose> attributes but without type constraints, attribute helpers or
+builder methods. This ensures that Catalyst 5.8 is fully backwards
+compatible to applications using the published API of Catalyst 5.7 but
+slightly limits the gains that could be had by wielding the full power
of L<Moose> attributes.
-Most of the accessors to information gathered during compile time is
-managed by C<Catalyst::ClassData>, which is a L<Moose>-aware version
-of L<Class::Data::Inheritable> but not compatible with
-L<MooseX::ClassAttribute>.
-
+Most of the accessors to information gathered during compile time (such
+as configuration) are managed by C<Catalyst::ClassData>, which is a
+L<Moose>-aware version of L<Class::Data::Inheritable> but not compatible
+with L<MooseX::ClassAttribute>.
=head2 ROLES AND METHOD MODIFIERS
-Since the release of Catalyst version 5.8 the only reason for creating
-a Catalyst extension as a plugin is to provide backward compatibility
+Since the release of Catalyst version 5.8, the only reason for creating
+a Catalyst extension as a plugin is to provide backward compatibility
to applications still using version 5.7.
-If backward compatibility is of no concern to you, you could as easily
-rewrite your plugins as roles and enjoy all the benefits of automatic
-method re-dispatching of C<< before >> and C<< after >> method
-modifiers, naming conflict detecting and generally cleaner code.
+If backward compatibility is of no concern to you, you could as easily
+rewrite your plugins as roles and enjoy all the benefits of automatic
+method re-dispatching of C<< before >> and C<< after >> method
+modifiers, naming conflict detection and generally cleaner code.
+
+=head3 NOTE
Plugins and roles should never use
after 'setup' => sub { ... } # wrong
-but rely on
+(or any other method of hooking the setup method) but rely on
after 'setup_finalize' => sub { ... } # this will work
-to run their own setup code if needed. If they need to influence the
-setup process itself, they can modify C<< setup_dispatcher() >>,
-C<< setup_engine() >>, C<< setup_stats() >>, C<< setup_components() >>
-and C<< setup_actions() >>, but this should be done with due
+to run their own setup code if needed. If they need to influence the
+setup process itself, they can modify C<< setup_dispatcher() >>,
+C<< setup_engine() >>, C<< setup_stats() >>, C<< setup_components() >>
+and C<< setup_actions() >>, but this should be done with due
consideration and as late as possible.
-
=head1 CONTROLLERS
-To activate Catalyst's action attributes, Moose-ified controller
-classes need to extend L<Catalyst::Controller> at compile time before
+To activate Catalyst's action attributes, Moose-ified controller
+classes need to extend L<Catalyst::Controller> at compile time, before
the actions themselves are declared:
package Catalyst::Controller::Root;
use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller'; }
- with qw(
- # your controller roles
- );
-
-
+
=head2 Controller Roles
It is possible to use roles to apply method modifiers on controller actions
-from 5.80003 onwards, or use modifiers in actions in your controller classes
-themselves.
+from 5.80003 onwards, or use modifiers in your controller classes
+themselves. For example
+ package MyApp::Controller::Foo;
+ use Moose;
+ use namespace::autoclean;
+ BEGIN { extends 'Catalyst::Controller' };
+
+ sub foo : Local {
+ my ($self, $c) = @_;
+ $c->res->body('Hello ');
+ }
+ after foo => sub {
+ my ($self, $c) = @_;
+ $c->res->body($c->res->body . 'World');
+ };
+
It is possible to have action methods with attributes inside Moose roles, using
-the trait introduced in L<MooseX::MethodAttributes> version 0.12, example:
+L<MooseX::MethodAttributes>, example:
package MyApp::ControllerRole;
- use Moose::Role -traits => 'MethodAttributes';
+ use MooseX::MethodAttributes::Role;
use namespace::autoclean;
-
+
sub foo : Local {
my ($self, $c) = @_;
...
}
+
+ package MyApp::Controller::Foo;
+ use Moose;
+ use namespace::autoclean;
+ BEGIN { extends 'Catalyst::Controller' };
+
+ with 'MyApp::ControllerRole';
+
+=head1 AUTHORS
+
+Catalyst Contributors, see Catalyst.pm
+
+=head1 COPYRIGHT
+
+This library is free software. You can redistribute it and/or modify it under
+the same terms as Perl itself.
+
+=cut