=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
=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>
=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
=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
=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>
=head3 Install
- $ perl -MCPAN -e 'install Bundle::Catalyst'
+ $ perl -MCPAN -e 'install Task::Catalyst'
=head3 Setup
=back
-Dead easy!
+Easy!
=head2 How It Works
=item * B<name>
-Name of your application.
+The name of your application.
=back
=item * L<Catalyst::Log>
$c->log
-
$c->log->debug('Something happened');
$c->log->info('Something you should know');
=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.
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') { }
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;
sub foo : Global { }
Matches http://localhost:3000/foo. The function name is mapped directly
to the application base.
-=item * B<Namespace-Prefixed>
+=item * B<Namespace-Prefixed> (B<Local>)
package MyApp::Controller::My::Controller;
sub foo : Local { }
=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
C<index> is much like C<default> except that it takes no arguments
and it is weighted slightly higher in the matching process. It is
useful as a static entry point to a controller, e.g. to have a static
-welcome page.
+welcome page. Note that it's also weighted higher than Path.
=item * B<begin : Private>
=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) = @_; }
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
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,
=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;
=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.
% sqlite /tmp/myapp.db < myapp.sql
-Now we can create a CDBI component for this database.
+Now we can create a DBIC::SchemaLoader component for this database.
- package MyApp::Model::CDBI;
+ script/myapp_create.pl model DBIC DBIC::SchemaLoader 'dbi:SQLite:/tmp/myapp.db'
- use strict;
- use base 'Catalyst::Model::CDBI';
+L<DBIx::Class::Schema::Loader> automatically loads table layouts and
+relationships. Use the stash to pass data to your templates.
- __PACKAGE__->config(
- dsn => 'dbi:SQLite:/tmp/myapp.db',
- relationships => 1
- );
+We add the following to MyApp/Controller/Root.pm
- 1;
-
-Catalyst automatically loads table layouts and relationships. Use the
-stash to pass data to your templates.
-
- package MyApp;
-
- 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');
+ $c->forward( $c->view('TT') );
}
- sub view : Global {
- my ( $self, $c, $id ) = @_;
- $c->stash->{item} = MyApp::Model::CDBI::Foo->retrieve($id);
- }
+We then create a new template file "root/index.tt" containing:
- 1;
-
- # 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:
# 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;
}
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
=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.