Catalyst-Manual
view release on metacpan or search on metacpan
lib/Catalyst/Manual/Intro.pod view on Meta::CPAN
This means that whenever your model/view/controller needs to talk to
C<$c> it gets a chance to do this when it's needed.
A typical C<ACCEPT_CONTEXT> method will either clone the model and return one
with the context object set, or it will return a thin wrapper that contains
C<$c> and delegates to the per-application model object.
Generally it's a bad idea to expose the context object (C<$c>) in your
model or view code. Instead you use the C<ACCEPT_CONTEXT> subroutine
to grab the bits of the context object that you need, and provide
accessors to them in the model. This ensures that C<$c> is only in
scope where it is needed which reduces maintenance and debugging
headaches. So, if for example you needed two
L<Catalyst::Model::DBIC::Schema> models in the same Catalyst model
code, you might do something like this:
__PACKAGE__->mk_accessors(qw(model1_schema model2_schema));
sub ACCEPT_CONTEXT {
my ( $self, $c, @extra_arguments ) = @_;
$self = bless({ %$self,
model1_schema => $c->model('Model1')->schema,
model2_schema => $c->model('Model2')->schema
}, ref($self));
return $self;
}
This effectively treats $self as a B<prototype object> that gets a new
parameter. C<@extra_arguments> comes from any trailing arguments to
C<< $c->component( $bah, @extra_arguments ) >> (or C<< $c->model(...)
>>, C<< $c->view(...) >> etc).
In a subroutine in the model code, we can then do this:
sub whatever {
my ($self) = @_;
my $schema1 = $self->model1_schema;
my $schema2 = $self->model2_schema;
...
}
Note that we still want the Catalyst models to be a thin wrapper
around classes that will work independently of the Catalyst
application to promote reusability of code. Here we might just want
to grab the C<< $c->model('DB')->schema >> so as to get the connection
information from the Catalyst application's configuration for example.
The life time of this value is B<per usage>, and not per request. To
make this per request you can use the following technique:
Add a field to C<$c>, like C<my_model_instance>. Then write your
C<ACCEPT_CONTEXT> method to look like this:
sub ACCEPT_CONTEXT {
my ( $self, $c ) = @_;
if ( my $per_request = $c->my_model_instance ) {
return $per_request;
} else {
my $new_instance = bless { %$self, c => $c }, ref($self);
Scalar::Util::weaken($new_instance->{c}); # or we have a circular reference
$c->my_model_instance( $new_instance );
return $new_instance;
}
}
For a similar technique to grab a new component instance on each
request, see L<Catalyst::Component::InstancePerContext>.
=head3 Application Class
In addition to the Model, View, and Controller components, there's a
single class that represents your application itself. This is where you
configure your application, load plugins, and extend Catalyst.
package MyApp;
use strict;
use parent qw/Catalyst/;
use Catalyst qw/-Debug ConfigLoader Static::Simple/;
MyApp->config(
name => 'My Application',
# You can put anything else you want in here:
my_configuration_variable => 'something',
);
1;
In older versions of Catalyst, the application class was where you put
global actions. However, as of version 5.66, the recommended practice is
to place such actions in a special Root controller (see L</Actions>,
below), to avoid namespace collisions.
=over 4
=item * B<name>
The name of your application.
=back
Optionally, you can specify a B<root> parameter for templates and static
data. If omitted, Catalyst will try to auto-detect the directory's
location. You can define as many parameters as you want for plugins or
whatever you need. You can access them anywhere in your application via
C<< $context->config->{$param_name} >>.
=head3 Context
Catalyst automatically blesses a Context object into your application
class and makes it available everywhere in your application. Use the
Context to directly interact with Catalyst and glue your L</Components>
together. For example, if you need to use the Context from within a
Template Toolkit template, it's already there:
<h1>Welcome to [% c.config.name %]!</h1>
As illustrated in our URL-to-Action dispatching example, the Context is
always the second method parameter, behind the Component object
reference or class name itself. Previously we called it C<$context> for
clarity, but most Catalyst developers just call it C<$c>:
( run in 1.539 second using v1.01-cache-2.11-cpan-39bf76dae61 )