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 Catalyst;
-
- $app->config( name => 'MyApp' );
- $app->setup(
+ use namespace::autoclean;
+ use Catalyst (
# your roles and plugins
);
-
- # method modifiers must be created after setup because otherwise they will
+ 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 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->setup >> are applied
-after the last plugin with all the benefits of using a single C<<
-with() >> statement in an ordinary L<Moose> class and that your class
-is automatically made immutable for you after the call to setup
-(method modifiers in your class will work, though).
+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.
-CAVEAT: using roles in C<< $c->setup >> was implemented in Catalyst
+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
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
-
-[Q: COULD THIS BE USED TO RESOLVE CONFLICTS IN ROLES?].
+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->stash>,
-C<$c->request> and C<$c->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
-to applications still using version 5.7 but even then you should
-consider building your plugin using L<Moose> and take advantage of
-L<Moose::Manual::MethodModifiers|method modifiers> instead of
-overriding methods to alter Catalyst's request lifecycle behavior.
+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 Moose;
- BEGIN{
- extends 'Catalyst::Controller';
- with(
- # your controller roles
- );
- }
-
-[MORE TO BE DONE!]
+ use namespace::autoclean;
+
+ BEGIN { extends 'Catalyst::Controller'; }
+
+=head2 Controller Roles
+
+It is possible to use roles to apply method modifiers on controller actions
+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
+L<MooseX::MethodAttributes>, example:
+
+ package MyApp::ControllerRole;
+ 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
+