modified to introduce Controller::Root
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Intro.pod
index e8b1c86..a75c5ca 100644 (file)
@@ -4,14 +4,15 @@ Catalyst::Manual::Intro - Introduction to Catalyst
 
 =head1 DESCRIPTION
 
-This is a brief overview of why and how to use Catalyst. It explains how
-Catalyst works and shows how to get a simple application up and running
-quickly.
+This is a brief introduction to Catalyst. It explains the most important
+features of how Catalyst works and shows how to get a simple application
+up and running quickly. For an introduction (without code) to Catalyst
+itself, and why you should be using it, see L<Catalyst::Manual::About>.
 
 =head2 What is Catalyst?
 
 Catalyst is an elegant web application framework, extremely flexible yet
-extremely simple. It's similar to Ruby on Rails, Spring (Java) and
+extremely simple. It's similar to Ruby on Rails, Spring (Java), and
 L<Maypole>, upon which it was originally based.
 
 =head3 MVC
@@ -30,7 +31,8 @@ well-known Perl modules you may want to use for each.
 
 =item * B<Model>
 
-Access and modify content (data). L<Class::DBI>, L<Plucene>, L<Net::LDAP>...
+Access and modify content (data). L<DBIx::Class>, L<Class::DBI>,
+L<Plucene>, L<Net::LDAP>...
 
 =item * B<View>
 
@@ -40,15 +42,15 @@ L<Mason|HTML::Mason>, L<HTML::Template>...
 =item * B<Controller>
 
 Control the whole request phase, check parameters, dispatch actions, flow
-control. Catalyst!
+control. Catalyst itself!
 
 =back
 
 If you're unfamiliar with MVC and design patterns, you may want to check
 out the original book on the subject, I<Design Patterns>, by Gamma,
-Helm, Johnson, and Vlissides, also known as the Gang of Four (GoF). You
-can also just Google it.  Many, many web application frameworks are
-based on MVC, including all those listed above.
+Helm, Johnson, and Vlissides, also known as the Gang of Four (GoF).
+Many, many web application frameworks are based on MVC, including all
+those listed above.
 
 =head3 Flexibility
 
@@ -78,7 +80,7 @@ multiple Catalyst applications.
 
 =item * B<Unrestrained URL-to-Action Dispatching>
 
-Catalyst allows you to dispatch any URLs to any application L<Actions>,
+Catalyst allows you to dispatch any URLs to any application L</Actions>,
 even through regular expressions! Unlike most other frameworks, it
 doesn't require mod_rewrite or class and method names in URLs.
 
@@ -108,7 +110,7 @@ simple way.
 =item * B<Building Block Interface>
 
 Components interoperate very smoothly. For example, Catalyst
-automatically makes a L<Context> object available to every
+automatically makes a L</Context> object available to every
 component. Via the context, you can access the request object, share
 data between components, and control the flow of your
 application. Building a Catalyst application feels a lot like snapping
@@ -121,8 +123,8 @@ and loads them.
 
 =item * B<Pre-Built Components for Popular Modules>
 
-See L<Catalyst::Model::CDBI> for L<Class::DBI>, or L<Catalyst::View::TT>
-for L<Template Toolkit|Template>.
+See L<Catalyst::Model::DBIC::Schema> for L<DBIx::Class>, or
+L<Catalyst::View::TT> for L<Template Toolkit|Template>.
 
 =item * B<Built-in Test Framework>
 
@@ -159,6 +161,10 @@ running, using the helper scripts described above.
 Now visit these locations with your favorite browser or user agent to see
 Catalyst in action:
 
+(NOTE: Although we create a controller here, we don't actually use it.
+Both of these URLs should take you to the welcome page.)
+
+
 =over 4
 
 =item http://localhost:3000/
@@ -167,7 +173,7 @@ Catalyst in action:
 
 =back
 
-Dead easy!
+Easy!
 
 =head2 How It Works
 
@@ -178,8 +184,7 @@ and other parts of a Catalyst application.
 
 In addition to the Model, View, and Controller components, there's a
 single class that represents your application itself. This is where you
-configure your application, load plugins, define application-wide
-actions, and extend Catalyst.
+configure your application, load plugins, and extend Catalyst.
 
     package MyApp;
 
@@ -192,22 +197,13 @@ actions, and extend Catalyst.
         # You can put anything else you want in here:
         my_configuration_variable => 'something',
     );
-
-    sub default : Private {
-        my ( $self, $context ) = @_;
-        $context->response->body('Catalyst rocks!');
-    }
-
     1;
 
-For most applications, Catalyst requires you to define only one config
-parameter:
-
 =over 4
 
 =item * B<name>
 
-Name of your application.
+The name of your application.
 
 =back
 
@@ -221,7 +217,7 @@ C<$context-E<gt>config-E<gt>{$param_name}>.
 
 Catalyst automatically blesses a Context object into your application
 class and makes it available everywhere in your application. Use the
-Context to directly interact with Catalyst and glue your L<Components>
+Context to directly interact with Catalyst and glue your L</Components>
 together. For example, if you need to use the Context from within a
 Template Toolkit template, it's already there:
 
@@ -275,7 +271,6 @@ information.
 =item * L<Catalyst::Log>
 
     $c->log
-
     $c->log->debug('Something happened');
     $c->log->info('Something you should know');
 
@@ -306,18 +301,48 @@ to maintain more persistent data, use a session.
 
 =head3 Actions
 
-A Catalyst controller is defined by its actions. An action is a sub with
-a special attribute. You've already seen some examples of actions in
-this document. The URL (for example http://localhost.3000/foo/bar)
-consists of two parts, the base (http://localhost:3000/ in this example)
-and the path (foo/bar).  Please note that the trailing slash after the
-hostname[:port] always belongs to base and not to the action.
+
+
+A Catalyst controller is defined by its actions. An action is a
+subroutine with a special attribute. You've already seen some examples
+of actions in this document. The URL (for example
+http://localhost.3000/foo/bar) consists of two parts, the base
+(http://localhost:3000/ in this example) and the path (foo/bar).  Please
+note that the trailing slash after the hostname[:port] always belongs to
+base and not to the action.
+
+=over 4
+
+=item * B<Application Wide Actions>
+
+Actions which are called at the root level of the application
+(e.g. http:///localhost:3000/ ) go in MyApp::Controller::Root, like
+this:
+
+    package MyApp::Controller::Root;
+    use base 'Catalyst::Controller';
+    # Sets the actions in this controller to be registered with no prefix
+    # so they function identically to actions created in MyApp.pm
+    __PACKAGE__->config->{namespace} = '';
+    sub default : Private {
+        my ( $self, $context ) = @_;
+        $context->response->body('Catalyst rocks!');
+    }
+    1;
+
+
+=back
+
+For most applications, Catalyst requires you to define only one config
+parameter:
+
+=head4 Action types
 
 Catalyst supports several types of actions:
 
 =over 4
 
-=item * B<Literal>
+=item * B<Literal> (B<Path> actions)
 
     package MyApp::Controller::My::Controller;
     sub bar : Path('foo/bar') { }
@@ -371,21 +396,25 @@ http://localhost:3000/catalog/foo/widget23 as well.
 
 For both LocalRegex and Regex actions, if you use capturing parentheses
 to extract values within the matching URL, those values are available in
-the C<$c-E<gt>req-E<gt>snippets> array. In the above example, "widget23"
+the C<$c-E<gt>req-E<gt>captures> array. In the above example, "widget23"
 would capture "23" in the above example, and
-C<$c-E<gt>req-E<gt>snippets-E<gt>[0]> would be "23". If you want to pass
+C<$c-E<gt>req-E<gt>captures-E<gt>[0]> would be "23". If you want to pass
 arguments at the end of your URL, you must use regex action keys. See
 L</URL Path Handling> below.
 
-=item * B<Top-level>
+=item * B<Top-level> (B<Global>)
 
-    package MyApp; 
+    package MyApp::Controller::Foo;
     sub foo : Global { }
 
-Matches http://localhost:3000/foo. The function name is mapped directly
-to the application base.
+Matches http://localhost:3000/foo. The function name is mapped
+directly to the application base.  You can provide an equivalent
+function in this case  by doing the following:
+
+    package MyApp::Controller::Root
+    sub foo : Local { }
 
-=item * B<Namespace-Prefixed>
+=item * B<Namespace-Prefixed> (B<Local>)
 
     package MyApp::Controller::My::Controller; 
     sub foo : Local { }
@@ -417,12 +446,27 @@ C<MyApp::Controller::Catalog::Order::Process> controller must, if called
 from elsewhere, be reached with
 C<$c-E<gt>forward('/catalog/order/process/bar')>.
 
+=item * B<Args>
+
+Args is not an action type per se, but an action modifier - it adds a match
+restriction to any action it's provided to, requiring only as many path parts
+as are specified for the action to be valid - for example in
+MyApp::Controller::Foo,
+
+  sub bar :Local
+
+would match any URL starting /foo/bar/. To restrict this you can do
+
+  sub bar :Local :Args(1)
+
+to only match /foo/bar/*/
+
 =back
 
 B<Note:> After seeing these examples, you probably wonder what the point
-is of defining names for regex and path actions. Actually, every public
-action is also a private one, so you have one unified way of addressing
-components in your C<forward>s.
+is of defining names for regex and path actions. Every public action is
+also a private one, so you have one unified way of addressing components
+in your C<forward>s.
 
 =head4 Built-in Private Actions
 
@@ -438,7 +482,7 @@ displaying a generic frontpage for the main app, or an error page for
 individual controllers.
 
 If C<default> isn't acting how you would expect, look at using a
-L<Literal> C<Path> action (with an empty path string). The difference is
+L</Literal> C<Path> action (with an empty path string). The difference is
 that C<Path> takes arguments relative from the namespace and C<default>
 I<always> takes arguments relative from the root, regardless of what
 controller it's in.
@@ -538,11 +582,10 @@ stage, without processing further actions.
 
 =head4 URL Path Handling
 
-You can pass variable arguments as part of the URL path. In this case,
-you must use regex action keys with '^' and '$' anchors, and the
-arguments must be separated with forward slashes (/) in the URL. For
-example, suppose you want to handle C</foo/$bar/$baz>, where C<$bar> and
-C<$baz> may vary:
+You can pass variable arguments as part of the URL path, separated with 
+forward slashes (/). If the action is a Regex or LocalRegex, the '$' anchor 
+must be used. For example, suppose you want to handle C</foo/$bar/$baz>, 
+where C<$bar> and C<$baz> may vary:
 
     sub foo : Regex('^foo$') { my ($self, $context, $bar, $baz) = @_; }
 
@@ -560,6 +603,10 @@ Catalyst matches actions in most specific to least specific order:
 So Catalyst would never mistakenly dispatch the first two URLs to the
 '^foo$' action.
 
+If a Regex or LocalRegex action doesn't use the '$' anchor, the action will 
+still match a URL containing arguments, however the arguments won't be 
+available via C<@_>.
+
 =head4 Parameter Processing
 
 Parameters passed in the URL query string are handled with methods in
@@ -628,10 +675,10 @@ be reset.
 
     sub check_message : Private {
         my ( $self, $c ) = @_;
-        my $first_argument = $c->req->args[0]; # now = 'test1'
+        my $first_argument = $c->req->args->[0]; # now = 'test1'
         # do something...
     }
-    
+
 As you can see from these examples, you can just use the method name as
 long as you are referring to methods in the same controller. If you want
 to forward to a method in another controller, or the main application,
@@ -673,12 +720,12 @@ method.
 
 =head3 Components
 
-Catalyst has an uncommonly flexible component system. You can define as many
-L<Models>, L<Views>, and L<Controllers> as you like.
+Catalyst has an uncommonly flexible component system. You can define as
+many L</Models>, L</Views>, and L</Controllers> as you like.
 
-All components must inherit from L<Catalyst::Base>, which provides a simple
-class structure and some common class methods like C<config> and C<new>
-(constructor).
+All components must inherit from L<Catalyst::Base>, which provides a
+simple class structure and some common class methods like C<config> and
+C<new> (constructor).
 
     package MyApp::Controller::Catalog;
 
@@ -756,7 +803,8 @@ eyecandy debug screen. ;)
 =head4 Models
 
 To show how to define models, again we'll use an already-existing base
-class, this time for L<Class::DBI>: L<Catalyst::Model::CDBI>.
+class, this time for L<DBIx::Class>: L<Catalyst::Model::DBIC::Schema>.
+We'll also need L<DBIx::Class::Schema::Loader>.
 
 But first, we need a database.
 
@@ -777,50 +825,33 @@ But first, we need a database.
 
     % sqlite /tmp/myapp.db < myapp.sql
 
-Now we can create a CDBI component for this database.
-
-    package MyApp::Model::CDBI;
-
-    use strict;
-    use base 'Catalyst::Model::CDBI';
+Now we can create a DBIC::SchemaLoader component for this database.
 
-    __PACKAGE__->config(
-        dsn           => 'dbi:SQLite:/tmp/myapp.db',
-        relationships => 1
-    );
-
-    1;
+    script/myapp_create.pl model DBIC DBIC::SchemaLoader 'dbi:SQLite:/tmp/myapp.db'
 
-Catalyst automatically loads table layouts and relationships. Use the
-stash to pass data to your templates.
+L<DBIx::Class::Schema::Loader> automatically loads table layouts and
+relationships. Use the stash to pass data to your templates.
 
-    package MyApp;
+We add the following to MyApp/Controller/Root.pm
 
-    use strict;
-    use Catalyst '-Debug';
+    sub view : Global {
+        my ( $self, $c, $id ) = @_;
+        
+        $c->stash->{item} = $c->model('DBIC::Foo')->find($id);
+    }
 
-    __PACKAGE__->config(
-        name => 'My Application',
-        root => '/home/joeuser/myapp/root'
-    );
+    1;
     
-    __PACKAGE__->setup;
-
     sub end : Private {
         my ( $self, $c ) = @_;
+        
         $c->stash->{template} ||= 'index.tt';
-        $c->forward('MyApp::View::TT');
-    }
-
-    sub view : Global {
-        my ( $self, $c, $id ) = @_;
-        $c->stash->{item} = MyApp::Model::CDBI::Foo->retrieve($id);
+        $c->forward( $c->view('TT') );
     }
 
-    1;
+We then create a new template file "root/index.tt" containing:
 
-    # Then, in a TT template:
-    The id is [% item.data %]
+    The Id's data is [% item.data %]
 
 Models do not have to be part of your Catalyst application; you
 can always call an outside module that serves as your Model:
@@ -828,9 +859,14 @@ can always call an outside module that serves as your Model:
     # in a Controller
     sub list : Local {
       my ( $self, $c ) = @_;
+      
       $c->stash->{template} = 'list.tt';
-      use Some::Outside::CDBI::Module;
-      my @records = Some::Outside::CDBI::Module->retrieve_all;
+      
+      use Some::Outside::DBIC::Module;
+      my @records = Some::Outside::DBIC::Module->search({
+        artist => 'sri',
+        });
+      
       $c->stash->{records} = \@records;
     }
 
@@ -847,12 +883,16 @@ write Catalyst models that can be used outside of Catalyst, e.g.
 in a cron job), it's trivial to write a simple component in
 Catalyst that slurps in an outside Model:
 
-    package MyApp::Model::Catalog;
-    use base qw/Catalyst::Base Some::Other::CDBI::Module::Catalog/;
+    package MyApp::Model::DB;
+    use base qw/Catalyst::Model::DBIC::Schema/;
+    __PACKAGE__->config(
+        schema_class => 'Some::DBIC::Schema',
+        connect_info => ['dbi:SQLite:foo.db', '', '', {AutoCommit=>1}]
+    );
     1;
 
-and that's it! Now C<Some::Other::CDBI::Module::Catalog> is part of your
-Cat app as C<MyApp::Model::Catalog>.
+and that's it! Now C<Some::DBIC::Schema> is part of your
+Cat app as C<MyApp::Model::DB>.
 
 =head4 Controllers
 
@@ -861,21 +901,48 @@ application.
 
     package MyApp::Controller::Login;
 
-    sub sign-in : Local { }
-    sub new-password : Local { }
-    sub sign-out : Local { }
+    use base qw/Catalyst::Controller/;
+
+    sub sign_in : Path("sign-in") { }
+    sub new_password : Path("new-password") { }
+    sub sign_out : Path("sign-out") { }
 
     package MyApp::Controller::Catalog;
 
+    use base qw/Catalyst::Controller/;
+
     sub view : Local { }
     sub list : Local { }
 
     package MyApp::Controller::Cart;
 
+    use base qw/Catalyst::Controller/;
+
     sub add : Local { }
     sub update : Local { }
     sub order : Local { }
 
+Note that you can also supply attributes via the Controller's config so long
+as you have at least one attribute on a subref to be exported (:Action is
+commonly used for this) - for example the following is equivalent to the same
+controller above
+
+    package MyApp::Controller::Login;
+
+    use base qw/Catalyst::Controller/;
+
+    __PACKAGE__->config(
+      actions => {
+        'sign_in' => { Path => 'sign-in' },
+        'new_password' => { Path => 'new-password' },
+        'sign_out' => { Path => 'sign-out' },
+      },
+    );
+
+    sub sign_in : Action { }
+    sub new_password : Action { }
+    sub sign_out : Action { }
+
 =head3 Testing
 
 Catalyst has a built-in http server for testing! (Later, you can easily
@@ -912,8 +979,9 @@ David Naughton, C<naughton@umn.edu>
 Marcus Ramberg, C<mramberg@cpan.org>
 Jesse Sheidlower, C<jester@panix.com>
 Danijel Milicevic, C<me@danijel.de>
+Kieren Diment, C<kd@totaldatasolution.com>
 
 =head1 COPYRIGHT
 
-This program is free software, you can redistribute it and/or modify it under
-the same terms as Perl itself.
+This program is free software, you can redistribute it and/or modify it
+under the same terms as Perl itself.