Fix capitalization in L<...> so links work in HTML.
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / ExtendingCatalyst.pod
index 9de413e..3cc5967 100644 (file)
@@ -46,9 +46,9 @@ forward to L</Namespaces>.
 
 =item Use the C<CatalystX::*> namespace if you can!
 
-If your extension isn't a Model, View, Controller, Plugin, or Engine,
-it's best to leave it out of the C<Catalyst::> namespace.  Use
-<CatalystX::> instead.
+If your extension isn't a Model, View, Controller, Plugin, Engine,
+or Log, it's best to leave it out of the C<Catalyst::> namespace.
+Use <CatalystX::> instead.
 
 =item Don't make it a plugin unless you have to!
 
@@ -56,6 +56,9 @@ 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.
 
+Also, if you think you really need a plugin, please instead consider
+using a L<Moose::Role>.
+
 =item There's a community. Use it!
 
 There are many experienced developers in the Catalyst community,
@@ -75,6 +78,9 @@ While some core extensions (engines, plugins, etc.) have to be placed
 in the C<Catalyst::*> namespace, the Catalyst core would like to ask
 developers to use the C<CatalystX::*> namespace if possible.
 
+Please B<do not> invent components which are outside the well
+known C<Model>, C<View>, C<Controller> or C<Plugin> namespaces!
+
 When you try to put a base class for a C<Model>, C<View> or
 C<Controller> directly under your C<MyApp> directory as, for example,
 C<MyApp::Controller::Foo>, you will have the problem that Catalyst
@@ -103,24 +109,37 @@ testing (and command-line scripts) a breeze.  The actual Catalyst
 Model is just a few lines of glue that makes working with the schema
 convenient.
 
-=head2 Inheritance and overriding methods
+If you want the thinnest interface possible, take a look at
+L<Catalyst::Model::Adaptor|Catalyst::Model::Adaptor>.
+
+=head2 Using Moose roles to apply method modifiers
 
-While Catalyst itself is still based on L<NEXT> (for multiple
-inheritance), extension developers are encouraged to use L<Class::C3>,
-which is what Catalyst will be switching to in some point in the
-future.
+Rather than having a complex set of base classes which you have to mixin
+via multiple inheritance, if your functionality is well structured, then
+it's possible to use the composability of L<Moose> roles, and method modifiers
+to hook onto to provide functionality.
 
-When overriding a method, keep in mind that some day additionally
+These can be applied to your models/views/controllers, and your application
+class, and shipped to CPAN.
+Please see L<Catalyst::Manual::CatalystAndMoose> for specific information
+about using Roles in combination with Catalyst, and L<Moose::Manual::Roles>
+for more information about roles in general.
+
+=head2 Inheritance and overriding methods
+
+When overriding a method, keep in mind that some day additional
 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
 you can pass your complete arguments to the original method via C<@_>:
 
-  use Class::C3; ...
+  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
 
@@ -210,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] );
   }
 
@@ -220,38 +238,58 @@ array reference. As you can see, you can use attributes to configure
 your actions. You can specify or alter these attributes via
 L</"Component Configuration">, or even react on them as soon as
 Catalyst encounters them by providing your own L<component base
-class|/"Component Base Classes">.
+class|/"Component base classes">.
 
-=head2 Creating custom accessors
-
-L<Catalyst::Component> uses L<Class::Accessor::Fast> for accessor
-creation. Please refer to the modules documentation for usage
-information.
-
-=head2 Component configuration
+=head2 Component Configuration
 
 At creation time, the class configuration of your component (the one
 available via C<$self-E<gt>config>) will be merged with possible
 configuration settings from the applications configuration (either
-directly or via config file).  This is then stored in the controller
-object's hash reference. So, if you read possible configurations like:
+directly or via config file). This is done by Catalyst, and the
+correctly merged configuration is passed to your component's
+constructor (i.e. the new method).
+
+Ergo, if you define an accessor for each configuration value
+that your component takes, then the value will be automatically stored
+in the controller object's hash reference, and available from the
+accessor.
+
+The C<config> accessor always only contains the original class configuration
+and you B<MUST NEVER> call $self->config to get your component configuration,
+as the data there is likely to be a subset of the correct config.
 
-  my $model_name = $controller->{model_name};
+For example:
 
-you will get the right value. The C<config> accessor always only
-contains the original class configuration and must not be used for
-component configuration.
+  package MyApp
+  use Moose;
+
+  extends 'Catalyst';
+
+  ...
 
-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<mk_ro_accessors> method provided to L<Catalyst::Component> via
-L<Class::Accessor::Fast>:
+  __PACKAGE__->config(
+    'Controller::Foo' => { some_value => 'bar' },
+  );
 
-  use base 'Catalyst::Controller';
-  __PACKAGE__->mk_ro_accessors('model_name');
   ...
-  my $model_name = $controller->model_name;
+
+  package MyApp::Controller::Foo;
+  use Moose;
+  use namespace::autoclean;
+  BEGIN { extends 'Catalyst::Controller' };
+
+  has some_value ( is => 'ro', required => 1 );
+
+  sub some_method {
+      my $self = shift;
+      return "the value of 'some_value' is " . $self->some_value;
+  }
+
+  ...
+
+  my $controller = $c->controller('Foo');
+  warn $controller->some_value;
+  warn $controller->some_method;
 
 =head1 IMPLEMENTATION
 
@@ -274,9 +312,11 @@ method. The execute method of the action will naturally call the
 methods code. You can surround this by overriding the method in a
 subclass:
 
-  package Catalyst::Action::MyFoo; use strict;
-
-  use Class::C3; use base 'Catalyst::Action';
+  package Catalyst::Action::MyFoo; 
+  use Moose;
+  use namespace::autoclean;
+  use MRO::Compat; 
+  extends 'Catalyst::Action';
 
   sub execute {
       my $self = shift;
@@ -288,8 +328,10 @@ subclass:
   }
   1;
 
-We are using L<Class::C3> to re-dispatch to the original C<execute> method
-in the L<Catalyst::Action> class.
+We are using L<MRO::Compat> to ensure that you have the next::method
+call, from L<Class::C3> (in older perls), or natively (if you are using 
+perl 5.10) to re-dispatch to the original C<execute> method in the 
+L<Catalyst::Action> class.
 
 The Catalyst dispatcher handles an incoming request and, depending
 upon the dispatch type, will call the appropriate target or chain. 
@@ -301,10 +343,11 @@ the action will match and add new matching criteria.
 For example, the action class below will make the action only match on
 Mondays:
 
-  package Catalyst::Action::OnlyMondays; use strict;
-
-  use Class::C3;
-  use base 'Catalyst::Action';
+  package Catalyst::Action::OnlyMondays; 
+  use Moose;
+  use namespace::autoclean;
+  use MRO::Compat;
+  extends 'Catalyst::Action';
 
   sub match {
       my $self = shift;
@@ -324,7 +367,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<Catalyst::Controller::ActionRole> allows you to apply L<Moose Roles|Moose::Role>
+to actions.
+
+For further information on action classes and roles, please refer to
 L<Catalyst::Action> and L<Catalyst::Manual::Actions>.
 
 =head2 Component base classes
@@ -348,8 +395,10 @@ already provided via the C<+> prefix for action classes. A simple
 
 will use C<MyApp::Action::Bar> 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) = @_;
@@ -362,8 +411,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') { ... }
 
@@ -380,8 +430,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) = @_;
@@ -389,13 +441,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<list> action chains
@@ -412,8 +464,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 },
@@ -480,9 +534,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) = @_;
@@ -520,16 +576,20 @@ object via L<Catalyst::Component/"ACCEPT_CONTEXT($c, @args)">.
 
 When is a plugin suited to your task? Your code needs to be a
 plugin to act upon or alter specific parts of Catalyst's request
-lifecycle. If your functionality needs to wrap some C<prepare_*> or
+lifecycle. If your functionality needs to change some C<prepare_*> or
 C<finalize_*> stages, you won't get around a plugin.
 
+Note, if you just want to hook into such a stage, and run code before,
+or after it, then it is recommended that you use L<Moose>s method modifiers
+to do this.
+
 Another valid target for a plugin architecture are things that
 B<really> have to be globally available, like sessions or
 authentication.
 
 B<Please do not> 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.
 
@@ -538,27 +598,48 @@ application's inheritance list, above Catalyst itself. You can by this
 alter Catalyst's request lifecycle behaviour. Every method you
 declare, every import in your package will be available as method on
 the application and the context object. As an example, let's say you
-want Catalyst to warn you every time uri_for returned an undefined
-value, for example because you specified the wrong number of captures
-for the targeted action chain. You could do this with this simple
+want Catalyst to warn you every time uri_for was called without an action
+object as the first parameter, for example to test that all your chained
+uris are generated from actions (a recommended best practice).
+You could do this with this simple
 implementation (excuse the lame class name, it's just an example):
 
   package Catalyst::Plugin::UriforUndefWarning;
   use strict;
-  use Class::C3;
+  use Scalar::Util qw/blessed/;
+  use MRO::Compat;
 
   sub uri_for {
       my $c = shift;
       my $uri = $c->next::method(@_);
-      $c->log->warn( 'uri_for returned undef for:', join(', ', @_), );
+      $c->log->warn( 'uri_for with non action: ', join(', ', @_), )
+        if (!blessed($_[0]) || !$_[0]->isa('Catalyst::Action'));
       return $uri;
   }
 
   1;
 
 This would override Catalyst's C<uri_for> method and emit a C<warn>
-log entry containing the arguments that led to the undefined return
-value.
+log entry containing the arguments to uri_for.
+
+Please note this is not a practical example, as string URLs are fine for
+static content etc.
+
+A simple example like this is actually better as a L<Moose> role, for example:
+
+  package CatalystX::UriforUndefWarning;
+  use Moose::Role;
+  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()
 
@@ -570,25 +651,29 @@ C<config>uration with the application wide overrides and call the
 class' C<new> method to return the component object.
 
 You can override this method and do and return whatever you want.
-However, you should use L<Class::C3> to forward to the original
-C<COMPONENT> method to merge the configuration of your component.
+However, you should use L<Class::C3> (via L<MRO::Compat>) to forward
+to the original C<COMPONENT> method to merge the configuration of
+your component.
 
 Here is a stub C<COMPONENT> method:
 
   package CatalystX::Component::Foo;
-  use strict;
-  use base 'Catalyst::Component';
-
-  use Class::C3;
+  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
@@ -599,22 +684,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<Catalyst::Component/"COMPONENT($c,$arguments)">.
+For more information, please see
+L<Catalyst::Component/"COMPONENT($c,$arguments)">.
+
+=head2 Applying roles to parts of the framework
+
+L<CatalystX::RoleApplicator> 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<Catalyst::TraitFor::XXX::YYYY>.
+
+For an example of a CPAN component implemented in this manor, see
+L<Catalyst::TraitFor::Request::BrowserDetect>.
 
 =head1 SEE ALSO
 
 L<Catalyst>, L<Catalyst::Manual::Actions>, L<Catalyst::Component>
 
-=head1 AUTHOR
-
-Robert Sedlacek C<< <rs@474.at> >>
+=head1 AUTHORS
 
-Jonathan Rockway C<< <jrockway@cpan.org> >>
+Catalyst Contributors, see Catalyst.pm
 
-=head1 LICENSE AND COPYRIGHT
+=head1 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
 
+