X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Manual.git;a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FExtendingCatalyst.pod;h=56e237a37f3044597d063631fb7eebbd4f1495b8;hp=dc88b5201dea996b5f66bd47b829f24554fa29aa;hb=e7cfb0cc7b727def160a320e0329ad866d6b2607;hpb=7817077652f226e9ff2af921c74e58d41f5a814e diff --git a/lib/Catalyst/Manual/ExtendingCatalyst.pod b/lib/Catalyst/Manual/ExtendingCatalyst.pod index dc88b52..56e237a 100644 --- a/lib/Catalyst/Manual/ExtendingCatalyst.pod +++ b/lib/Catalyst/Manual/ExtendingCatalyst.pod @@ -56,7 +56,8 @@ A plugin should be careful since it's overriding Catalyst internals. If your plugin doesn't really need to muck with the internals, make it a base Controller or Model. -If you need to hook (but not alter) the internals, then make it a L +Also, if you think you really need a plugin, please instead consider +using a L. =item There's a community. Use it! @@ -77,6 +78,9 @@ While some core extensions (engines, plugins, etc.) have to be placed in the C namespace, the Catalyst core would like to ask developers to use the C namespace if possible. +Please B invent components which are outside the well +known C, C, C or C namespaces! + When you try to put a base class for a C, C or C directly under your C directory as, for example, C, you will have the problem that Catalyst @@ -113,21 +117,17 @@ L. Rather than having a complex set of base classes which you have to mixin via multiple inheritence, if your functionality is well structured, then it's possible to use the composability of L roles, and method modifiers -to hook onto to provide functionality. - -For a simple example of this, see L. +to hook onto to provide functionality. -B Currently, controllers with attributes will not function correctly -in conjunction with Moose roles. +These can be applied to your models/views/controllers, and your application +class, and shipped to CPAN. +Please see L for specific information +about using Roles in combination with Catalyst, and L +for more information about roles in general. =head2 Inheritance and overriding methods -While Catalyst itself is still based on L (for multiple -inheritance), extension developers are encouraged to use L, -via L, which is what Catalyst will be switching to in the -5.80 release. - -When overriding a method, keep in mind that some day additionally +When overriding a method, keep in mind that some day additionall arguments may be provided to the method, if the last parameter is not a flat list. It is thus better to override a method by shifting the invocant off of C<@_> and assign the rest of the used arguments, so @@ -135,9 +135,11 @@ you can pass your complete arguments to the original method via C<@_>: use MRO::Compat; ... - sub foo { my $self = shift; - my ($bar, $baz) = @_; # ... return - $self->next::method(@_); } + sub foo { + my $self = shift; + my ($bar, $baz) = @_; # ... return + $self->next::method(@_); + } If you would do the common @@ -227,8 +229,7 @@ action: sub foo : Local Bar('Baz') { my ($self, $c) = @_; - my $attributes = - $self->action_for('foo')->attributes; + my $attributes = $self->action_for('foo')->attributes; $c->res->body($attributes->{Bar}[0] ); } @@ -261,12 +262,17 @@ component configuration. You are advised to create accessors on your component class for your configuration values. This is good practice and makes it easier to -capture configuration key typos. You can do this with the -C method provided to L via -L: +capture configuration key typos, or missing keys. + +You can do this with L: + + package MyApp::Controller::Foo; + use Moose; + use namespace::autoclean; + BEGIN { extends 'Catalyst::Controller' }; + + has model_name ( is => 'ro', required => 1 ); - use base 'Catalyst::Controller'; - __PACKAGE__->mk_ro_accessors('model_name'); ... my $model_name = $controller->model_name; @@ -292,10 +298,10 @@ methods code. You can surround this by overriding the method in a subclass: package Catalyst::Action::MyFoo; - use strict; - + use Moose; + use namespace::autoclean; use MRO::Compat; - use base 'Catalyst::Action'; + extends 'Catalyst::Action'; sub execute { my $self = shift; @@ -323,10 +329,10 @@ For example, the action class below will make the action only match on Mondays: package Catalyst::Action::OnlyMondays; - use strict; - + use Moose; + use namespace::autoclean; use MRO::Compat; - use base 'Catalyst::Action'; + extends 'Catalyst::Action'; sub match { my $self = shift; @@ -346,7 +352,11 @@ If you are using action classes often or have some specific base classes that you want to specify more conveniently, you can implement a component base class providing an attribute handler. -For further information on action classes, please refer to +It is not possible to use multiple action classes at once, however +L allows you to apply L +to actions. + +For further information on action classes and roles, please refer to L and L. =head2 Component base classes @@ -370,8 +380,10 @@ already provided via the C<+> prefix for action classes. A simple will use C as action class. - package MyApp::Base::Controller::FullClass; use strict; use base - 'Catalyst::Controller'; + package MyApp::Base::Controller::FullClass; + use Moose; + use namespace::autoclean; + BEGIN { extends 'Catalyst::Controller'; } sub _parse_FullClass_attr { my ($self, $app_class, $action_name, $value, $attrs) = @_; @@ -384,8 +396,9 @@ sake. We could use this attribute in a subclass like any other Catalyst attribute: package MyApp::Controller::Foo; - use strict; - use base 'MyApp::Base::Controller::FullClass'; + use Moose; + use namespace::autoclean; + BEGIN { extends 'MyApp::Base::Controller::FullClass'; } sub foo : Local FullClass('MyApp::Action::Bar') { ... } @@ -402,8 +415,10 @@ controller object, or you can even define Catalyst actions which will be inherited by the subclasses. Consider this controller base class: package MyApp::Base::Controller::ModelBase; - use strict; - use base 'Catalyst::Controller'; + use Moose; + use namespace::autoclean; + + BEGIN { extends 'Catalyst::Controller'; } sub list : Chained('base') PathPart('') Args(0) { my ($self, $c) = @_; @@ -411,13 +426,13 @@ be inherited by the subclasses. Consider this controller base class: my $condition = $self->{model_search_condition} || {}; my $attrs = $self->{model_search_attrs} || {}; $c->stash(rs => $model->search($condition, $attrs); - } + } sub load : Chained('base') PathPart('') CaptureArgs(1) { my ($self, $c, $id) = @_; my $model = $c->model( $self->{model_name} ); $c->stash(row => $model->find($id)); - } + } 1; This example implements two simple actions. The C action chains @@ -434,8 +449,10 @@ The class above is not very useful on its own, but we can combine it with some custom actions by sub-classing it: package MyApp::Controller::Foo; - use strict; - use base 'MyApp::Base::Controller::ModelBase'; + use Moose; + use namespace::autoclean; + + BEGIN { extends 'MyApp::Base::Controller::ModelBase'; } __PACKAGE__->config( model_name => 'DB::Foo', model_search_condition=> { is_active => 1 }, @@ -502,9 +519,11 @@ generation. Here is some example code for a fictional view: - package CatalystX::View::MyView; - use strict; - use base 'Catalyst::View'; + package Catalyst::View::MyView; + use Moose; + use namespace::autoclean; + + extends 'Catalyst::View'; sub process { my ($self, $c) = @_; @@ -555,7 +574,7 @@ authentication. B release Catalyst extensions as plugins only to provide some functionality application wide. Design it as a controller -base class or another suiting technique with a smaller scope, so that +base class or another better suited technique with a smaller scope, so that your code only influences those parts of the application where it is needed, and namespace clashes and conflicts are ruled out. @@ -595,14 +614,17 @@ A simple example like this is actually better as a L role, for example: package CatalystX::UriforUndefWarning; use Moose::Role; - use namespace::clean -except => 'meta'; + use namespace::autoclean; after 'uri_for' => sub { my ($c, $arg) = @_; $c->log->warn( 'uri_for with non action: ', join(', ', @_), ) if (!blessed($_[0]) || !$_[0]->isa('Catalyst::Action')); return $uri; - }; + }; + +Note that Catalyst will load any Moose Roles in the plugin list, +and apply them to your application class. =head2 Factory components with COMPONENT() @@ -614,26 +636,29 @@ Curation with the application wide overrides and call the class' C method to return the component object. You can override this method and do and return whatever you want. -However, you should use L (via L) to forward -to the original C method to merge the configuration of +However, you should use L (via L) to forward +to the original C method to merge the configuration of your component. Here is a stub C method: package CatalystX::Component::Foo; - use strict; - use base 'Catalyst::Component'; - - use MRO::Compat; + use Moose; + use namespace::autoclean; + + extends 'Catalyst::Component'; sub COMPONENT { my $class = shift; - my ($app_class, $config) = @_; - - # do things here before instantiation my - $obj = $self->next::method(@_); - # do things to object after instantiation - return $object; + # Note: $app is like $c, but since the application isn't fully + # initialized, we don't want to call it $c yet. $config + # is a hashref of config options possibly set on this component. + my ($app, $config) = @_; + + # Do things here before instantiation + $new = $class->next::method(@_); + # Do things to object after instantiation + return $new; } The arguments are the class name of the component, the class name of @@ -644,22 +669,48 @@ You are free to re-bless the object, instantiate a whole other component or really do anything compatible with Catalyst's expectations on a component. -For more information, please see L. +For more information, please see +L. + +=head2 Applying roles to parts of the framework + +L will allow you to apply Roles to +the following classes: + +=over + +=item Request + +=item Response + +=item Engine + +=item Dispatcher + +=item Stats + +=back + +These roles can add new methods to these classes, or wrap preexisting methods. + +The namespace for roles like this is C. + +For an example of a CPAN component implemented in this manor, see +L. =head1 SEE ALSO L, L, L -=head1 AUTHOR +=head1 AUTHORS -Robert Sedlacek C<< >> +Catalyst Contributors, see Catalyst.pm -Jonathan Rockway C<< >> +=head1 COPYRIGHT -=head1 LICENSE AND COPYRIGHT - -This document is free, you can redistribute it and/or modify it under +This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself. =cut +