Catalyst is the latest in the evolution of open-source Web development
frameworks. Written in modern Perl and inspired by many of the projects
that came before it, including Ruby on Rails, Catalyst is elegant, powerful
and refined. It’s a great choice for creating any Web-based application
from the simple to the very complex.
Like many other popular Perl-based projects, Catalyst has a strong focus on
flexibility and choice. Catalyst is especially powerful because it provides
an abundance of features and the core environment, structure and
interfaces on which virtually anything can be built without forcing you to
do things in any particular way.
Writing applications in Catalyst is fast too. Just because you can tackle
any aspect of application design yourself, doesn’t mean you have to.
Catalyst provides a wide array of refined, high-level, drop-in solutions to
all kinds of problems and needs without limiting access to the nuts and bolts.
Templating, ORM, authentication, automatic session management and all the
other high-level features you’d want from a Web framework are available in
Catalyst—and more.
Catalyst’s approach is to provide these high-level features as optional
plugins and modules. This is one of the greatest strengths of Perl—a
tremendous number of refined modules and libraries are available. So,
instead of re-inventing all this functionality, Catalyst provides a
framework to bring together seamlessly what already exists.
Catalyst is bigger than itself—it is also everything that’s available in
CPAN. That alone makes it one of the most feature-rich frameworks there
are.
In this article, I provide an introduction to Catalyst and how to use it
for rapid application development. I cover the basics of how to
create and lay out a new application as well as how to write the actions
that will handle requests. I explain how to define flexible URL dispatch
logic and some of the APIs that are available. I focus on the
fundamentals, but I cover some of the popular available components as well, such as Template::Toolkit. I also talk about how you can
extend Catalyst itself, and how you can deploy an application with Apache.
Background Knowledge and the MVC Architecture
Catalyst and Catalyst applications are written in Perl, so some basic Perl
knowledge is necessary to use Catalyst effectively. You also should have
some experience with object-oriented programming concepts, such as classes,
methods, inheritance and so on.
Like Rails, Django, CakePHP and many other Web frameworks, Catalyst follows
the venerable Model-View-Controller architectural pattern. MVC is a
proven approach to structuring and segmenting application code for
efficiency, flexibility and maintainability.
Plenty of tutorials and resources are available for MVC, so
I won’t spend too much time covering it here. If you’ve
worked with other Web frameworks, chances are you’re already familiar with
MVC. If not, the most important thing to understand is that it is more
about best practices than anything else.
The focus of this article is to explain the core details of how Catalyst
operates, but since Catalyst made most of its layout decisions according to
MVC, you’ll still see it along the way.
Getting Catalyst
Before you can install Catalyst on your system, you obviously need Perl.
Most Linux distros already have Perl installed out of the box, but if not,
install it with your package manager.
Catalyst itself is a Perl library that you can install with cpan:
cpan Catalyst::Devel
The previous command installs Catalyst with development tools along with
its many dependencies. For production/hosting systems that will run
only applications without the need for development tools, you can install the
smaller Catalyst::Runtime bundle instead.
Because Catalyst has so many dependencies, it can take quite a while to
install on a fresh system. By default, CPAN asks if it should install each
dependency individually, which can become redundant really quick. You can
configure CPAN not to ask, but instead, I usually just cheat by holding
down Enter for a few seconds to queue up a bunch of default (“yes, install
the module!”) keystroke/answers.
If the install fails on the first attempt, don’t fret. Whatever the problem
may be, it probably will be explained in the scrollback along with what to
do to solve it. Typically, this involves nothing more than
installing/upgrading another module that wasn’t automatically in the
dependency tree for whatever reason, or just running the
cpan command a
second time.
Catalyst Application Layout
Every Catalyst application is a Perl module/library/bundle—exactly like
the modules on CPAN. This consists of a package/class namespace and
standard structure of files and directories. The Catalyst::Devel package
comes with a helper script to create new “skeleton” applications and to
initialize the files and directories for you. For example, to create a new
application called KillerApp, run the following:
catalyst.pl KillerApp
This creates a new application structure at KillerApp/ with the
following subdirectories:
lib/: this is the Perl include directory
that stores all the Perl
classes (aka packages or modules) for the application. This is added to
the Perl lib path at runtime, and the directory structure corresponds to the
package/class namespaces. For example, the two classes that are initially
created have the following namespaces and corresponding file paths:
These directories also are created but initially are empty:
-
lib/KillerApp/Model/
-
lib/KillerApp/View/
root/: this is where other kinds application-specific files are
stored. Static Web files, such as images, CSS and JavaScript go in the
subdirectory static, which usually is exposed as the URL /static. Other
kinds of files go in here too, such as templates.
script/: this contains application-specific scripts, including the
development server (killerapp_server.pl) that you can use to run the
application in its own standalone Web server, as well as scripts to deploy
the application in a “real” Web server. The helper script
killerapp_create.pl creates new model, view and controller component
classes.
t/: this is where “tests” go. If you follow a test-driven
development process, for every new feature you write, you also will write an
automated test case. Tests let you quickly catch regressions that may be
introduced in the future. Writing them is a good habit to get into, but
that’s
beyond the scope of this article.
The created skeleton application is already fully functional, and you can
run it using the built-in test server:
cd KillerApp/
script/killerapp_server.pl
This fires up the app in its own dedicated Web server on port 3000. Open
http://localhost:3000/ to see the default front page, which initially
displays the Catalyst welcome message.
The Request/Response Cycle
All Web applications handle requests and generate responses. The
fundamental job of any Web framework/platform/environment is to provide a
useful structure to manage this process. Although there are different ways of
going about this—from elegant MVC applications to ugly, monolithic CGI
scripts—ultimately, they’re all doing the same basic thing:
Decide what to call when a request comes in.
Supply an API for generating the response.
In Catalyst, this happens in special methods called “actions”. On every
request, Catalyst identifies one or more actions and calls them with
special arguments, including a reference to the “context”
object that
provides a convenient and practical API through which everything else is
accomplished.
Actions are contained within classes called “controllers”, which live in a
special path/namespace in the application (lib/KillerApp/Controller/). The
skeleton application sets up one controller (“Root”), but you can create
more with the helper script. For example, this creates a new
controller class KillerApp::Controller::Something:
script/killerapp_create.pl controller Something
The only reason to have more than one controller is for organization; you
can put all your actions in the Root controller with no loss of features or
ability. Controllers are just the containers for actions.
In the following sections, I describe how Catalyst decides which actions
to call on each request (“dispatch”) and then explain how to use the
supplied context object within them.
Linux Journal – The Original Magazine of the Linux Community