Introduction to Catalyst, the Perl MVC Framework

NOTE: Click the Maximize button ( ) in the upper right corner for wide-screen view. You can also zoom out in your browser.

At its native resolution, the presentation below requires a resolution of at least ~1000 horizontal pixels for the Flash screencast, and >1200px for having the transcript scroll at the side. Works great in Firefox 3 but if you have issues with other browsers after setting the resolution high enough, or zooming out, please let me know.


In this screencast, we'll create our first Catalyst application, examine its structure, and get a basic understanding of how it works.


We will need a working installation of Perl 5.8 or later. I'll be using Strawberry Perl 5.10 on Windows XP. To install Catalyst from cpan, run cpan Catalyst::Runtime. We'll also install Catalyst::Devel, which provides among other things, a helper script called '' which creates a skeleton Catalyst application.

While the installation is underway, let's add that the version of Catalyst we're installing is 5.8005, released on June 6th, 2009. This is just two weeks ago, at the time of recording this screencast. Catalyst development is indeed very active, with 86 committers to the Subversion repository.

Creating a skeleton app

After the installation is complete, we'll run the helper script to create a skeleton application called TinyURL. This will be our yet-another URL shortening application, but built with Catalyst.

Examining the application's structure

Let's take a look at the TinyURL directory structure that created. The lib directory contains your application's Perl modules. The root directory hosts templates, form definitions and static files (CSS, JavaScript, images etc.) In script/, we'll find 5 Perl scripts associated with the application:

  • - runs your application as CGI (not recommended)
  • - is a helper script for creating models, views and controllers
  • - runs your application as FastCGI, which is the preferred deployment method
  • - is the development server script, and we'll run this one in a minute
  • - lets you test your application from the command line

The t directory contains a test suite skeleton

  • 01app.t - checks if the application can be loaded
  • 02pod.t, 03podcoverage.t - documentation tests

Makefile.PL enables you to build the application (notice that Catalyst applications are structured as CPAN modules, ready for publishing).

We then have boilerplate Changes and README files, and the application's configuration file, tinyurl.conf, which for now only specifies the application name.

Let's go back to the lib directory.

The base module is the base module. It specifies which version of Catalyst is the minimum requirement (Catalyst switched to using Moose since version 5.8). We inherit our application class form Catalyst, and pass some parameters:

  • -Debug - flag to display a debug screen
  • ConfigLoader - tells Catalyst to use the ConfigLoader plugin, which reads the tinyurl.conf file that we've seen before
  • Static::Simple - plugin to serve the static files from the root/ directory

Below we define the version number, configure the application and start it.

Next, there is some autogenerated POD that you just have to fill in. So no more excuses for not documenting your code.

In the TinyURL directory, we have the MVC subdirectories. We have no model and no view for now.

The Root controller

In Controller, we have, which handles requests for the root application path. In our example, if we had "" as the domain name, the root path would be "".

The root controller inherits from Catalyst::Controller and defines an empty namespace, which basically means that it handles the root path.

The index() method does the actual handling of requests for the root path. It has two attributes: Path, and Args, which specify that it matches all paths (there is nothing like 'foo' after Path, and it takes no arguments after the /. When a request to '/' is made, index() will send an HTTP response containing the Catalyst welcome message.

If an HTTP request doesn't match what index() expects, it will be dispatched to default(), which returns a "Page not found" message, and a 404 error code.

At the end of any request, the special method "end" is called.

Let's see how this dispatching works by running the application right now.

Running the application

To do that, we change directory to TinyURL and we run from the script\ directory, the script. This is the development server.

Let's take a look at the debug screen, which we enabled with the -Debug flag before.

It shows that Catalyst loaded the ConfigLoader and Static::Simple plugins, and that it read the tinyurl.conf file.

Our controller class was instantiated and the actions it defined were loaded. We see index, default, and the paths they listen at. By default the Catalyst development server runs on localhost port 3000. Let's surf there.

We are greeted with the welcome page, as expected. If we add a /foo path, we'll get the "Page not found" error message. Same happens for /foo/bar. Let's now go to the debug screen and see what happened.

The requests on the debug screen

On the debug screen, we can see that we had a request for '/', and the index action matched, then the automatic action end was called.

Next, we had a request for foo, which didn't match what index was expecting, that is, no path or arguments, so Catalyst fell back to default. Again, end followed.

The same happened for /foo/bar.

Our first customization

Now let's go back to and change the attributes of the index() method. We'll set Path to foo and Args to 2. This means that index will be called only if the URL starts with /foo and is followed by 2 arguments. We'll also change the HTTP response so that instead of the welcome message it will just say that it matched the index action.

After saving the file, we'll go back to the debug screen, Ctrl+C the server, and start it again.

This time, if we surf to /foo/bar/baz, index() will match. If we surf to any other URL, index() will not match and Catalyst will call the default() action.

Conclusion (Part 1)

This concludes Part 1 of "Introduction to Catalyst".

We've seen what makes up a Catalyst application, and how HTTP requests are dispatched.

In Part 2, we'll add database access and venture into CRUD.


Buy me a coffee to sponsor more cool posts like this!

My tags:
Popular tags:
  Perl Catalyst screencast