Catalyst::Manual::Tutorial::CatalystBasics - Catalyst Tutorial - Part 2: Catalyst Application Development Basics
-
=head1 OVERVIEW
This is B<Part 2 of 9> for the Catalyst tutorial.
=item 3
-L<Basic CRUD|Catalyst::Manual::Tutorial_BasicCRUD>
+L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
=item 4
=item 8
-L<AdvancedCRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
+L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
=item 9
-L<Appendicies|Catalyst::Manual::Tutorial::Appendicies>
+L<Appendices|Catalyst::Manual::Tutorial::Appendicies>
=back
-
-
=head1 DESCRIPTION
In this part of the tutorial, we will create a very basic Catalyst web
Model/View/Controller (MVC) provides an architecture that facilitates a
clean "separation of control" between the different portions of your
-application. Given that many other documents cover this subject in
+application. Given that many other documents cover this subject in
detail, MVC will not be discussed in depth here (for an excellent
introduction to MVC and general Catalyst concepts, please see
-L<Catalyst::Manual::About|Catalyst::Manual::About>. In short:
+L<Catalyst::Manual::About>. In short:
=over 4
=item * Model
-In most applications, the model equates to the objects that are created
-from and saved to your SQL database.
+The model usually represents a data store. In most applications, the
+model equates to the objects that are created from and saved to your SQL
+database.
=item * View
The view takes model objects and renders them into something for the end
-user to look at. Normally this involves a template-generation tool that
+user to look at. Normally this involves a template-generation tool that
creates HTML for the user's web browser, but it could easily be code
-that generates other forms such as PDF documents or Excel spreadsheets.
+that generates other forms such as PDF documents, e-mails, or Excel
+spreadsheets.
=item * Controller
=item * ORM
-The use Object-Relational Mapping (ORM) technology for database access
-(specifically, ORM provides an automated means to persist and restore
-objects to/from a relational database).
+The use of Object-Relational Mapping (ORM) technology for database
+access. Specifically, ORM provides an automated and standardized means
+to persist and restore objects to/from a relational database.
=back
IMPORTANT: Does not work yet. Will be completed for final version.
-
=head1 CREATE A CATALYST PROJECT
Catalyst provides a number of helper scripts that can be used to quickly
-flesh out the basic structure of your application. All Catalyst
-projects begin with the C<catalyst.pl> helper.
+flesh out the basic structure of your application. All Catalyst projects
+begin with the C<catalyst.pl> helper.
In the case of this tutorial, use the Catalyst C<catalyst.pl> script to
initialize the framework for an application called C<MyApp>:
The C<catalyst.pl> helper script will display the names of the
directories and files it creates.
-Though it's obviously too early for any significant celebration, we
-already have a functioning application. Run the following command to
-run this application with the built-in development web server:
+Though it's too early for any significant celebration, we already have a
+functioning application. Run the following command to run this
+application with the built-in development web server:
$ script/myapp_server.pl
greeted by the Catalyst welcome screen. Press Ctrl-C to break out of
the development server.
-
-
=head1 CREATE A SQLITE DATABASE
In this step, we make a text file with the required SQL commands to
INSERT INTO book_authors VALUES (5, 8);
B<TIP>: See Appendix 1 for tips on removing the leading spaces when
-cutting and pasting example code from Pod documents.
+cutting and pasting example code from POD documents.
Then use the following command to build a C<myapp.db> SQLite database:
your OS command prompt.
-
=head1 EDIT THE LIST OF CATALYST PLUGINS
One of the greatest benefits of Catalyst is that it has such a large
L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader>
-C<ConfigLoader> provides an automatic way to load your configurable
+C<ConfigLoader> provides an automatic way to load configurable
parameters for your application from a central YAML file (versus having
the values hard-coded inside your Perl modules). If you have not been
exposed to YAML before, it is a human-readable data serialization format
see how to use this feature of Catalyst during the authentication and
authorization sections (Part 4 and Part 5).
-
=item *
-L<Catalyst::Plugin::Static::Simple|Catalyst::Plugin::Static::Simple>
+L<Catalyst::Plugin::Static::Simple>
C<Static::Simple> provides an easy method of serving static content such
as images and CSS files under the development server.
ConfigLoader
Static::Simple
- Dumper
StackTrace
DefaultEnd
/;
=item *
-L<Catalyst::Plugin::Dumper|Catalyst::Plugin::Dumper>
-
-Allows you to easily use L<Data::Dumper|Data::Dumper> to dump variables
-to the logs, for example:
-
- $c->log->dumper($myvar);
-
-When running your application under the development server, the logs
-will be printed to your screen along with the other debug information
-generated by the C<-Debug> flag.
-
-=item *
-
L<Catalyst::Plugin::StackTrace|Catalyst::Plugin::StackTrace>
Adds a stack trace to the standard Catalyst "debug screen" (this is the
screen Catalyst sends to your browser when an error occurs).
-Note: L<Dumper|Catalyst::Plugin::Dumper> output appears on the
-console/telnet/SSH window where you issue the C<script/myapp_server.pl>
-command. L<StackTrace|Catalyst::Plugin::StackTrace> output appears in
-your browser.
+Note: L<StackTrace|Catalyst::Plugin::StackTrace> output appears in your
+browser, not in the console window from which you're running your
+application, which is where logging output usually goes.
=item *
with "?" or "&" depending on where it is in the URL) to I<force> the
debug screen at the end of the Catalyst request processing cycle.
-TIP: Many Catalyst-related documents predate
+B<TIP>: Many Catalyst-related documents predate
L<DefaultEnd|Catalyst::Plugin::DefaultEnd> and suggest that you add an
C<end> action to your application class (C<MyApp.pm>) or Root.pm
(C<MyApp/Controller/Root.pm>). In most of these cases, you can convert
to L<DefaultEnd|Catalyst::Plugin::DefaultEnd> by deleting the C<end>
-action and using the plugin instead.
+action and using the plugin instead. There are certainly cases when
+you'd want to write your own custom C<end> action, but for most
+circumstances, DefaultEnd will be exactly what you want.
=back
Note that when specifying plugins on the C<use Catalyst> line, you can
-omit C<Catalyst::Plugin> from the name. Additionally, you can spread
+omit C<Catalyst::Plugin::> from the name. Additionally, you can spread
the plugin names across multiple lines as shown here, or place them all
on one (or more) lines as with the default configuration.
-
-
=head1 DATABASE ACCESS WITH C<DBIx::Class>
Catalyst can be used with virtually any form of persistent datastore
-available via Perl. For example,
-L<Catalyst::Model::DBI|Catalyst::Model::DBI> can be used to easily
-access databases through the traditional Perl DBI interface. However,
-most Catalyst applications use some form of ORM technology to
+available via Perl. For example, L<Catalyst::Model::DBI> can be used to
+easily access databases through the traditional Perl L<DBI> interface.
+However, most Catalyst applications use some form of ORM technology to
automatically create and save model objects as they are used. Although
-Tony Bowden's L<Class::DBI|Class::DBI> has been the traditional Perl ORM
-engine, Matt Trout's L<DBIx::Class|DBIx::Class> (abbreviated as "DBIC")
-has rapidly emerged as the Perl-based ORM technology of choice. Most
-new Catalyst applications rely on DBIC, as will this tutorial.
-
-Note: See L<Catalyst::Model::CDBI| Catalyst:: Model::CDBI > for more
-information on using Catalyst with L<Class::DBI|Class::DBI>. Catalyst
-can also be used with "plain old DBI"; see L<Catalyst::Model::DBI|
-Catalyst::Model::DBI>.
+Tony Bowden's L<Class::DBI> has been the traditional Perl ORM engine,
+Matt Trout's L<DBIx::Class> (abbreviated as "DBIC") has rapidly emerged
+as the Perl-based ORM technology of choice. Most new Catalyst
+applications rely on DBIC, as will this tutorial.
+Note: See L<Catalyst:: Model::CDBI > for more information on using
+Catalyst with L<Class::DBI>.
=head2 Create a DBIC Schema File
DBIx::Class uses a schema file to load other classes that represent the
tables in your database (DBIC refers to these "table objects" as "result
-sources," see L<DBIx::Class::ResultSource|DBIx::Class::ResultSource>).
-In this case, we want to load the model object for the C<books>,
-C<book_authors>, and C<authors> tables created in the previous step.
+sources"; see L<DBIx::Class::ResultSource>). In this case, we want to
+load the model object for the C<books>, C<book_authors>, and C<authors>
+tables created in the previous step.
Open C<lib/MyAppDB.pm> in your editor and insert:
=head1 NAME
- MyAppDB -- DBIC Schema Class
+ MyAppDB - DBIC Schema Class
=cut
B<Note:> C<__PACKAGE__> is just a shorthand way of referencing the name
of the package where it is used. Therefore, in C<MyAppDB.pm>,
-C<__PACKAGE> is equivalent to C<MyAppDB>
+C<__PACKAGE__> is equivalent to C<MyAppDB>
=head2 Create the DBIC "Result Source" Files
In this step, we create "table classes" (again, these are called a
-"result source" classes in DBIC) that acts as model objects for the
+"result source" classes in DBIC) that act as model objects for the
C<books>, C<book_authors>, and C<authors> tables in our database.
First, create a directory to hold the class:
C<$book-E<gt>book_authors-E<gt>first-E<gt>author-E<gt>last_name> (we
will see examples on how to use DBIC objects in your code soon, but note
that because C<$book-E<gt>book_authors> can return multiple authors, we
-have to use C<first> to display a single author). C<many_to_many>
-allows us to use the shorter
-C<$book-E<gt>authors-E<gt>first-E<gt>last_name>. Note that you cannot
-define a C<many_to_many> relationship without also having the
-C<has_many> relationship in place.
+have to use C<first> to display a single author). C<many_to_many> allows
+us to use the shorter C<$book-E<gt>authors-E<gt>first-E<gt>last_name>.
+Note that you cannot define a C<many_to_many> relationship without also
+having the C<has_many> relationship in place.
Next, open C<lib/MyAppDB/Author.pm> in your editor and enter:
objects (e.g., C<Book> and C<Author>); however, Catalyst places no
restrictions on the naming conventions you wish to use.
-
=head2 Use C<Catalyst::Model::DBIC::Schema> To Load The Model Class
-When L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema> is
+When L<Catalyst::Model::DBIC::Schema> is
in use, Catalyst essentially reads an existing copy of your database
model and creates a new set of objects under C<MyApp::Model> for use
inside of Catalyst.
-B<Note:> With
-L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema> you
-essentially end up with two sets of model classes (only one of which you
-write... the other set is created automatically in memory when your
-Catalyst application initializes). For this tutorial application, the
-important points to remember are: you write the I<result source> files
-in C<MyAppDB>, but I<within Catalyst> you use the I<automatically
-created model classes> in C<MyApp::Model>.
+B<Note:> With L<Catalyst::Model::DBIC::Schema> you essentially end up
+with two sets of model classes (only one of which you write... the other
+set is created automatically in memory when your Catalyst application
+initializes). For this tutorial application, the important points to
+remember are: you write the I<result source> files in C<MyAppDB>, but
+I<within Catalyst> you use the I<automatically created model classes> in
+C<MyApp::Model>.
-Use the L<Catalyst::Helper::Model::DBIC::Schema|
-Catalyst::Helper::Model::DBIC::Schema > helper script to create the
-model class that loads up the model we created in the previous step:
+Use the L<Catalyst::Helper::Model::DBIC::Schema > helper script to
+create the model class that loads up the model we created in the
+previous step:
$ script/myapp_create.pl model MyAppDB DBIC::Schema MyAppDB dbi:SQLite:myapp.db '' '' '{ AutoCommit => 1 }'
applications often use the directories C<M>, C<V>, and C<C>]).
-
=head1 CREATE A CATALYST CONTROLLER
-Controllers are where you write methods that respond to C<GET> and C<POST> messages from the user's web browser.
+Controllers are where you write methods that interact with user
+input--typically, controller methods respond to C<GET> and C<POST>
+messages from the user's web browser.
-Use the Catalyst C<create> script to add a controller for book-related actions:
+Use the Catalyst C<create> script to add a controller for book-related
+actions:
$ script/myapp_create.pl controller Books
Nicholas Clark's C<attributes> module to provide additional information
to the Catalyst dispatcher logic.
-
=head1 CATALYST VIEWS
-Views are where you render output for display in the user's web browser
-(or possibly using other display technology). As with virtually every
-aspect of Catalyst, options abound when it comes to the specific view
-technology you adopt inside your application. However, most Catalyst
-applications use the Template Toolkit, known as TT (for more information
-on TT, see L<http://www.template-toolkit.org>). Other popular View
-technologies include Mason (L<http://www.masonhq.com> and
-L<http://www.masonbook.com>) and L<HTML::Template|HTML::Template>
+Views are where you render output, typically for display in the user's
+web browser, but also possibly using other display our output-generation
+systems. As with virtually every aspect of Catalyst, options abound
+when it comes to the specific view technology you adopt inside your
+application. However, most Catalyst applications use the Template
+Toolkit, known as TT (for more information on TT, see
+L<http://www.template-toolkit.org>). Other popular View technologies
+include Mason (L<http://www.masonhq.com> and
+L<http://www.masonbook.com>) and L<HTML::Template>
(L<http://html-template.sourceforge.net>).
-
=head2 Create a Catalyst View Using C<TTSITE>
When using TT for the Catalyst view, there are two main helper scripts:
=item *
-L<Catalyst::Helper::View::TT|Catalyst::Helper::View::TT>
+L<Catalyst::Helper::View::TT>
=item *
-L<Catalyst::Helper::View::TTSite|Catalyst::Helper::View::TTSite>
+L<Catalyst::Helper::View::TTSite>
=back
Both are similar, but C<TT> merely creates the C<lib/MyApp/View/TT.pm>
file and leaves the creation of any hierarchical template organization
-entirely up to you (it also creates a C<t/view_TT.t> file for testing;
-test cases will be discussed in Part 7). Conversely, the C<TTSite>
-helper creates a modular and hierarchical view layout with separate
-Template Toolkit (TT) files for common header and footer information,
-configuration values, a CSS stylesheet, etc.
+entirely up to you. (It also creates a C<t/view_TT.t> file for testing;
+test cases will be discussed in Part 7). The C<TTSite> helper creates a
+modular and hierarchical view layout with separate Template Toolkit (TT)
+files for common header and footer information, configuration values, a
+CSS stylesheet, and more.
Enter the following command to enable the C<TTSite> style of view
-rendering for the tutorial:
+rendering for this tutorial:
$ script/myapp_create.pl view TT TTSite
B<TIP>: Note that TTSite does one thing that could confuse people who
are used to the normal C<TT> Catalyst View: it redefines the Catalyst
-context object in templates from its usual C<c> to C<Catalyst>. Also
-keep this in mind when looking at other Catalyst examples (they almost
-always use C<c>). Note that Catalyst and TT I<do not complain> when you
-use the wrong name to access the context... it simply outputs blanks for
+context object in templates from its usual C<c> to C<Catalyst>. When
+looking at other Catalyst examples, remember that they almost always use
+C<c>. Note that Catalyst and TT I<do not complain> when you use the
+wrong name to access the context object...TT simply outputs blanks for
that bogus logic. Finally, be aware that this change in name I<only>
-applies to how the context object is accessed inside your TT templates,
+applies to how the context object is accessed inside your TT templates;
your controllers will continue to use C<$c> (or whatever name you use
-when fetching the reference from C<@_> inside your methods). (You can
+when fetching the reference from C<@_> inside your methods). (You can
change back to the "default" behavior be removing the C<CATALYST_VAR>
line from C<lib/MyApp/View/TT.pm>, but you will also have to edit
C<root/lib/config/main> and C<root/lib/config/url>. If you do this, be
careful not to have a collision between your own C<c> variable and the
Catalyst C<c> variable.)
-
-
=head2 Globally Customize Every View
When using TTSite, files in the subdirectories of C<root/lib> can be
used to make changes that will appear in every view. For example, to
display optional status and error messages in every view, edit
-C<root/lib/site/layout> update it to match the following (the two HTML
+C<root/lib/site/layout>, updating it to match the following (the two HTML
C<span> elements are new):
<div id="header">[% PROCESS site/header %]</div>
<div id="footer">[% PROCESS site/footer %]</div>
If we set either message in the Catalyst stash (e.g.,
-C<$c-E<gt>stash-E<gt>{status_msg} = 'Hello world'>) it will be displayed
-whenever any view used by that request is rendered. The C<message> and
-C<error> CSS styles are automatically defined in C<root/src/ttsite.css>
-and can be customized to suit your needs.
+C<$c-E<gt>stash-E<gt>{status_msg} = 'Request was successful!'>) it will
+be displayed whenever any view used by that request is rendered. The
+C<message> and C<error> CSS styles are automatically defined in
+C<root/src/ttsite.css> and can be customized to suit your needs.
B<Note:> The Catalyst stash only lasts for a single HTTP request. If
you need to retain information across requests you can use
-L<Catalyst::Plugin::Session|Catalyst::Plugin::Session> (we will use
+L<Catalyst::Plugin::Session> (we will use
Catalyst sessions in the Authentication part).
cell (a simple space is used between the names; in reality you would
probably want to modify the code to use a comma as a separator).
-If you are new to TT, the [% and %] tags are used to delimit "variable
-text". TT supports a wide variety of directives for "calling" other
+If you are new to TT, the C<[%> and C<%]> tags are used to delimit TT
+code. TT supports a wide variety of directives for "calling" other
files, looping, conditional logic, etc. In general, TT simplifies the
usual range of Perl operators down to the single dot (C<.>) operator.
This applies to operations as diverse as method calls, hash lookups, and
consistency with the files already created by the C<TTSite> helper.
-
=head1 RUN THE APPLICATION
First, let's enable an environment variable option that causes
B<NOTE>: You can also set this in your code using
C<$class-E<gt>storage-E<gt>debug(1);>. See
-L<DBIx::Class::Manual::Troubleshooting|DBIx::Class::Manual::Troubleshooting>
-for details (including options to log to file vs. the Catalyst
-development server log.
+L<DBIx::Class::Manual::Troubleshooting> for details (including options
+to log to file instead of displaying to the Catalyst development server
+log).
Then run the Catalyst "demo server" script:
.------------------------------------------------------------------------------.
| Catalyst::Plugin::ConfigLoader 0.07 |
| Catalyst::Plugin::Static::Simple 0.14 |
- | Catalyst::Plugin::Dumper 0.000002 |
| Catalyst::Plugin::StackTrace 0.04 |
| Catalyst::Plugin::DefaultEnd 0.06 |
'------------------------------------------------------------------------------'
=back
-
Point your browser to L<http://localhost:3000> and you should still get
the Catalyst welcome page.
Please report any errors, issues or suggestions to the author.
-Copyright 2006, Kennedy Clark, under Creative Commons License (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
+Copyright 2006, Kennedy Clark, under Creative Commons License
+(L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
Version: .94