Welcome to the world of Catalyst.
This MVC
framework will make web development something you had
never expected it to be: Fun, rewarding, and quick.
What to do now?
That really depends on what you want to do.
We do, however, provide you with a few starting points.
If you want to jump right into web development with Catalyst
you might want to start with a tutorial.
perldoc Catalyst::Manual::Tutorial
Afterwards you can go on to check out a more complete look at our features.
perldoc Catalyst::Manual::Intro
What to do next?
Next it's time to write an actual application. Use the
helper scripts to generate controllers,
models, and
views;
they can save you a lot of work.
script/${prefix}_create.pl --help
Also, be sure to check out the vast and growing
collection of plugins for Catalyst on CPAN;
you are likely to find what you need there.
Need help?
Catalyst has a very active community. Here are the main places to
get in touch with us.
In conclusion
The Catalyst team hopes you will enjoy using Catalyst as much
as we enjoyed making it. Please contact us if you have ideas
for improvement or other feedback.
EOF
}
=head2 run_options
Contains a hash of options passed from the application script, including
the original ARGV the script received, the processed values from that
ARGV and any extra arguments to the script which were not processed.
This can be used to add custom options to your application's scripts
and setup your application differently depending on the values of these
options.
=head1 INTERNAL METHODS
These methods are not meant to be used by end users.
=head2 $c->components
Returns a hash of components.
=head2 $c->context_class
Returns or sets the context class.
=head2 $c->counter
Returns a hashref containing coderefs and execution counts (needed for
deep recursion detection).
=head2 $c->depth
Returns the number of actions on the current internal execution stack.
=head2 $c->dispatch
Dispatches a request to actions.
=cut
sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
=head2 $c->dispatcher_class
Returns or sets the dispatcher class.
=head2 $c->dump_these
Returns a list of 2-element array references (name, structure) pairs
that will be dumped on the error page in debug mode.
=cut
sub dump_these {
my $c = shift;
[ Request => $c->req ],
[ Response => $c->res ],
[ Stash => $c->stash ],
[ Config => $c->config ];
}
=head2 $c->engine_class
Returns or sets the engine class.
=head2 $c->execute( $class, $coderef )
Execute a coderef in given class and catch exceptions. Errors are available
via $c->error.
=cut
sub execute {
my ( $c, $class, $code ) = @_;
$class = $c->component($class) || $class;
#$c->state(0);
if ( $c->depth >= $RECURSION ) {
my $action = $code->reverse();
$action = "/$action" unless $action =~ /->/;
my $error = qq/Deep recursion detected calling "${action}"/;
$c->log->error($error);
$c->error($error);
$c->state(0);
return $c->state;
}
my $stats_info = $c->_stats_start_execute( $code ) if $c->use_stats;
push( @{ $c->stack }, $code );
no warnings 'recursion';
# N.B. This used to be combined, but I have seen $c get clobbered if so, and
# I have no idea how, ergo $ret (which appears to fix the issue)
eval { my $ret = $code->execute( $class, $c, @{ $c->req->args } ) || 0; $c->state( $ret ) };
$c->_stats_finish_execute( $stats_info ) if $c->use_stats and $stats_info;
my $last = pop( @{ $c->stack } );
if ( my $error = $@ ) {
#rethow if this can be handled by middleware
if ( $c->_handle_http_exception($error) ) {
foreach my $err (@{$c->error}) {
$c->log->error($err);
}
$c->clear_errors;
$c->log->_flush if $c->log->can('_flush');
$error->can('rethrow') ? $error->rethrow : croak $error;
}
if ( blessed($error) and $error->isa('Catalyst::Exception::Detach') ) {
$error->rethrow if $c->depth > 1;
}
elsif ( blessed($error) and $error->isa('Catalyst::Exception::Go') ) {
$error->rethrow if $c->depth > 0;
}
else {
unless ( ref $error ) {
no warnings 'uninitialized';
chomp $error;
my $class = $last->class;
my $name = $last->name;
$error = qq/Caught exception in $class->$name "$error"/;
}
$c->error($error);
}
#$c->state(0);
}
return $c->state;
}
sub _stats_start_execute {
my ( $c, $code ) = @_;
my $appclass = ref($c) || $c;
return if ( ( $code->name =~ /^_.*/ )
&& ( !$appclass->config->{show_internal_actions} ) );
my $action_name = $code->reverse();
$c->counter->{$action_name}++;
my $action = $action_name;
$action = "/$action" unless $action =~ /->/;
# determine if the call was the result of a forward
# this is done by walking up the call stack and looking for a calling
# sub of Catalyst::forward before the eval
my $callsub = q{};
for my $index ( 2 .. 11 ) {
last
if ( ( caller($index) )[0] eq 'Catalyst'
&& ( caller($index) )[3] eq '(eval)' );
if ( ( caller($index) )[3] =~ /forward$/ ) {
$callsub = ( caller($index) )[3];
$action = "-> $action";
last;
}
}
my $uid = $action_name . $c->counter->{$action_name};
# is this a root-level call or a forwarded call?
if ( $callsub =~ /forward$/ ) {
my $parent = $c->stack->[-1];
# forward, locate the caller
if ( defined $parent && exists $c->counter->{"$parent"} ) {
$c->stats->profile(
begin => $action,
parent => "$parent" . $c->counter->{"$parent"},
uid => $uid,
);
}
else {
# forward with no caller may come from a plugin
$c->stats->profile(
begin => $action,
uid => $uid,
);
}
}
else {
# root-level call
$c->stats->profile(
begin => $action,
uid => $uid,
);
}
return $action;
}
sub _stats_finish_execute {
my ( $c, $info ) = @_;
$c->stats->profile( end => $info );
}
=head2 $c->finalize
Finalizes the request.
=cut
sub finalize {
my $c = shift;
for my $error ( @{ $c->error } ) {
$c->log->error($error);
}
# Support skipping finalize for psgix.io style 'jailbreak'. Used to support
# stuff like cometd and websockets
if($c->request->_has_io_fh) {
$c->log_response;
return;
}
# Allow engine to handle finalize flow (for POE)
my $engine = $c->engine;
if ( my $code = $engine->can('finalize') ) {
$engine->$code($c);
}
else {
$c->finalize_uploads;
# Error
if ( $#{ $c->error } >= 0 ) {
$c->finalize_error;
}
$c->finalize_encoding;
$c->finalize_headers unless $c->response->finalized_headers;
$c->finalize_body;
}
$c->log_response;
if ($c->use_stats) {
my $elapsed = $c->stats->elapsed;
my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
$c->log->info(
"Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
}
return $c->response->status;
}
=head2 $c->finalize_body
Finalizes body.
=cut
sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
=head2 $c->finalize_cookies
Finalizes cookies.
=cut
sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
=head2 $c->finalize_error
Finalizes error. If there is only one error in L and it is an object that
does C