X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FIntro.pod;h=b6823ef869f9019802cd32ce74ddc72df9e0d267;hb=24cda51b9aafb235b2b839200810b7624606f47a;hp=561956ec6de89c90692939becf69e539bbfb0ce2;hpb=2982e768f25cf78c0cab330b2d61acd850d5e760;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Manual/Intro.pod b/lib/Catalyst/Manual/Intro.pod index 561956e..b6823ef 100644 --- a/lib/Catalyst/Manual/Intro.pod +++ b/lib/Catalyst/Manual/Intro.pod @@ -46,11 +46,11 @@ control. Catalyst itself! =back -If you're unfamiliar with MVC and design patterns, you may want to check -out the original book on the subject, I, by Gamma, -Helm, Johnson, and Vlissides, also known as the Gang of Four (GoF). -Many, many web application frameworks are based on MVC, including all -those listed above. +If you're unfamiliar with MVC and design patterns, you may want to +check out the original book on the subject, I, by +Gamma, Helm, Johnson, and Vlissides, also known as the Gang of Four +(GoF). Many, many web application frameworks are based on MVC, which +is becoming a popular design method for web applications. =head3 Flexibility @@ -161,6 +161,10 @@ running, using the helper scripts described above. Now visit these locations with your favorite browser or user agent to see Catalyst in action: +(NOTE: Although we create a controller here, we don't actually use it. +Both of these URLs should take you to the welcome page.) + + =over 4 =item http://localhost:3000/ @@ -180,8 +184,7 @@ and other parts of a Catalyst application. 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, define application-wide -actions, and extend Catalyst. +configure your application, load plugins, and extend Catalyst. package MyApp; @@ -194,17 +197,8 @@ actions, and extend Catalyst. # You can put anything else you want in here: my_configuration_variable => 'something', ); - - sub default : Private { - my ( $self, $context ) = @_; - $context->response->body('Catalyst rocks!'); - } - 1; -For most applications, Catalyst requires you to define only one config -parameter: - =over 4 =item * B @@ -284,6 +278,10 @@ information. $c->stash $c->stash->{foo} = 'bar'; + $c->stash->{baz} = {baz => 'qox'}; + $c->stash->{fred} = [qw/ wilma pebbles/]; + +and so on. =back @@ -307,6 +305,8 @@ to maintain more persistent data, use a session. =head3 Actions + + A Catalyst controller is defined by its actions. An action is a subroutine with a special attribute. You've already seen some examples of actions in this document. The URL (for example @@ -315,6 +315,33 @@ http://localhost.3000/foo/bar) consists of two parts, the base note that the trailing slash after the hostname[:port] always belongs to base and not to the action. +=over 4 + +=item * B + +Actions which are called at the root level of the application +(e.g. http:///localhost:3000/ ) go in MyApp::Controller::Root, like +this: + + package MyApp::Controller::Root; + use base 'Catalyst::Controller'; + # Sets the actions in this controller to be registered with no prefix + # so they function identically to actions created in MyApp.pm + __PACKAGE__->config->{namespace} = ''; + sub default : Private { + my ( $self, $context ) = @_; + $context->response->body('Catalyst rocks!'); + } + 1; + + +=back + +For most applications, Catalyst requires you to define only one config +parameter: + +=head4 Action types + Catalyst supports several types of actions: =over 4 @@ -381,11 +408,15 @@ L below. =item * B (B) - package MyApp; + package MyApp::Controller::Foo; sub foo : Global { } -Matches http://localhost:3000/foo. The function name is mapped directly -to the application base. +Matches http://localhost:3000/foo. The function name is mapped +directly to the application base. You can provide an equivalent +function in this case by doing the following: + + package MyApp::Controller::Root + sub foo : Local { } =item * B (B) @@ -419,6 +450,21 @@ C controller must, if called from elsewhere, be reached with C<$c-Eforward('/catalog/order/process/bar')>. +=item * B + +Args is not an action type per se, but an action modifier - it adds a match +restriction to any action it's provided to, requiring only as many path parts +as are specified for the action to be valid - for example in +MyApp::Controller::Foo, + + sub bar :Local + +would match any URL starting /foo/bar/. To restrict this you can do + + sub bar :Local :Args(1) + +to only match /foo/bar/*/ + =back B After seeing these examples, you probably wonder what the point @@ -859,21 +905,145 @@ application. package MyApp::Controller::Login; - sub sign-in : Local { } - sub new-password : Local { } - sub sign-out : Local { } + use base qw/Catalyst::Controller/; + + sub sign_in : Path("sign-in") { } + sub new_password : Path("new-password") { } + sub sign_out : Path("sign-out") { } package MyApp::Controller::Catalog; + use base qw/Catalyst::Controller/; + sub view : Local { } sub list : Local { } package MyApp::Controller::Cart; + use base qw/Catalyst::Controller/; + sub add : Local { } sub update : Local { } sub order : Local { } +Note that you can also supply attributes via the Controller's config so long +as you have at least one attribute on a subref to be exported (:Action is +commonly used for this) - for example the following is equivalent to the same +controller above + + package MyApp::Controller::Login; + + use base qw/Catalyst::Controller/; + + __PACKAGE__->config( + actions => { + 'sign_in' => { Path => 'sign-in' }, + 'new_password' => { Path => 'new-password' }, + 'sign_out' => { Path => 'sign-out' }, + }, + ); + + sub sign_in : Action { } + sub new_password : Action { } + sub sign_out : Action { } + +=head3 Models + +Models are providers of data. This data could come from anywhere - a search +engine index, a database table, etc. Typically the data source does not have +much to do with web applications or Catalyst - it could be used to write an +offline report generator or a command line tool just the same. + +The common approach to writing a Catalyst-style model for your application is +wrapping a generic model (e.g. L, a bunch of XMLs, or +anything really) with an object that contains configuration data, convenience +methods, and so forth. + +#### editor: move this part to =head3 Components somehow, right after this +#### section - this will require deeply rephrasing this paragraph. + +Technically, within Catalyst a model is a B - an instance of the +model's class belonging to the application. It is important to stress that the +lifetime of these objects is per application, not per request. + +While the model base class (L) provides things like C +and stuff to better integrate the model into the application, sometimes this is +not enough, and the model requires access to C<$c> itself. + +Situations where this need might arise include: + +=over 4 + +=item * + +Interacting with another model + +=item * + +Using per-request data to control behavior + +=item * + +Using plugins in (for example L). + +=back + +From a style perspective usually it's bad to make your model "too smart" about +things - it should worry about business logic and leave the integration details +to the controllers. If, however, you find that it does not make sense at all to +use an auxillary controller around the model, and the model's need to access +C<$c> cannot be sidestepped, there exists a power tool called C. + +#### editor note: this part is "generic" - it also applies to views and +#### controllers. + +=head3 ACCEPT_CONTEXT + +Whenever you call $c->component("Foo") you get back an object - the instance of +the model. If the component supports the C method instead of +returning the model itself, the return value of +C<< $model->ACCEPT_CONTEXT( $c ) >> will be used. + +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 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. + +A typicall C method could look like this: + + sub ACCEPT_CONTEXT { + my ( $self, $c, @extra_arguments ) = @_; + bless { %$self, c => $c }, ref($self); + } + +effectively treating $self as a B 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). + +The life time of this value is B, and not per request. To make this +per request you can use the following technique: + +Add a field to C<$c>, like C. Then write your +C 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; + } + } + + + =head3 Testing Catalyst has a built-in http server for testing! (Later, you can easily @@ -910,6 +1080,8 @@ David Naughton, C Marcus Ramberg, C Jesse Sheidlower, C Danijel Milicevic, C +Kieren Diment, C +Yuval Kogman, C =head1 COPYRIGHT