X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FIntro.pod;h=cb09eebda97ca105334a0ea8e2e3b33cc6901277;hb=6b10c72bff517a4eab3b52aa7f31e1a4cd499484;hp=b59ad62db0717094717f74ee888c774621a517a9;hpb=2ef2fb0f3a712ba1239a5fed7e332ced3bbe663f;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Manual/Intro.pod b/lib/Catalyst/Manual/Intro.pod index b59ad62..cb09eeb 100644 --- a/lib/Catalyst/Manual/Intro.pod +++ b/lib/Catalyst/Manual/Intro.pod @@ -376,10 +376,11 @@ application, by calling the C method: $c->forward('foo'); See L for a full explanation of C. Note that, as -discussed there, when forwarding from another component, you must use the -absolute path to the method, so that a private C method in your -C controller must, if called from -elsewhere, be reach with C<$c-Eforward('/catalog/order/process/bar')>. +discussed there, when forwarding from another component, you must use +the absolute path to the method, so that a private C method in your +C controller must, if called +from elsewhere, be reached with +C<$c-Eforward('/catalog/order/process/bar')>. =back @@ -390,66 +391,84 @@ components in your Cs. =head4 Built-in Private Actions -In response to specific application states, Catalyst will automatically call -these built-in private actions: +In response to specific application states, Catalyst will automatically +call these built-in private actions in your application class: =over 4 =item * B -Called when no other action matches. +Called when no other action matches. Could be used, for example, for +displaying a generic frontpage for the main app, or an error page for +individual controllers. =item * B -Called at the beginning of a request, before any matching actions are called. +Called at the beginning of a request, before any matching actions are +called. =item * B -=back - Called at the end of a request, after all matching actions are called. -=head4 B +=back + +=head4 Built-in actions in controllers/autochaining Package MyApp::C::Foo; sub begin : Private { } sub default : Private { } - -You can define the Built-in Private Actions within your controllers as -well. The actions will override the ones in lower level controllers or -your global application. - -In addition to the normal built-ins, you have a special action for -making inheritance chains, 'auto'. These will be run after C, -but before your action is processed. + sub auto : Private { } + +You can define built-in private actions within your controllers as +well. The actions will override the ones in less-specific controllers, +or your application class. In other words, for each of the three +built-in private actions, only one will be run in any request +cycle. Thus, if C exists, it will be run in +place of C if you're in the C namespace, and +C would override this in turn. + +In addition to the normal built-in actions, you have a special action +for making chains, C. Such C actions will be run after any +C, but before your action is processed. Unlike the other +built-ins, C actions I override each other; they will be +called in turn, starting with the application class and going through to +the I specific class. I. + +Here are some examples of the order in which the various built-ins +would be called: =over 4 -=item for a request for /foo/foo +=item for a request for C MyApp::begin MyApp::auto - MyApp::C::Foo::default + MyApp::C::Foo::default # in the absence of MyApp::C::Foo::Foo MyApp::end -=item for a request for /foo/bar/foo +=item for a request for C MyApp::C::Foo::Bar::begin MyApp::auto MyApp::C::Foo::auto - MyApp::C::Foo::Bar::default + MyApp::C::Foo::Bar::auto + MyApp::C::Foo::Bar::default # for MyApp::C::Foo::Bar::foo MyApp::C::Foo::Bar::end =back -Also, if you need to break out of the chain in one of your auto -actions, you can return 0, if so, your action will not be processed, -but the end will, so for the request above, if the first auto returns -false, it would look like this: +The C action is also distinguished by the fact that you can break +out of the processing chain by returning 0. If an C action returns +0, any remaining actions will be skipped, except for C. So, for the +request above, if the first auto returns false, the chain would look +like this: =over 4 -=item for a request for /foo/bar/foo where auto returns false +=item for a request for C where first C returns +false MyApp::C::Foo::Bar::begin MyApp::auto @@ -457,22 +476,28 @@ false, it would look like this: =back -B auto actions have to return a true value to continue -processing! You can also die in the autochain action, in that case, the -request will go straight to the finalize stage, without processing -further actions. +An example of why one might use this is an authentication action: you +could set up a C action to handle authentication in your +application class (which will always be called first), and if +authentication fails, returning 0 would skip any remaining methods +for that URL. +B Looking at it another way, C actions have to return a +true value to continue processing! You can also C in the autochain +action; in that case, the request will go straight to the finalize +stage, without processing further actions. -=head4 B +=head4 URL Path Handling -If you want to pass variable arguments at the end of a URL, you must use regex -actions keys with '^' and '$' anchors, and the arguments must be separated with -forward slashes (/) in the URL. For example, suppose you want to handle -/foo/$bar/$baz, where $bar and $baz may vary: +You can pass variable arguments as part of the URL path. In this case, +you must use regex action keys with '^' and '$' anchors, and the +arguments must be separated with forward slashes (/) in the URL. For +example, suppose you want to handle C, where C<$bar> and +C<$baz> may vary: sub foo : Regex('^foo$') { my ($self, $context, $bar, $baz) = @_; } -But what if you also defined actions for /foo/boo and /foo/boo/hoo ? +But what if you also defined actions for C and C? sub boo : Path('foo/boo') { .. } sub hoo : Path('foo/boo/hoo') { .. } @@ -481,15 +506,17 @@ Catalyst matches actions in most specific to least specific order: /foo/boo/hoo /foo/boo - /foo # might be /foo/bar/baz + /foo # might be /foo/bar/baz but won't be /foo/boo/hoo -So Catalyst would never mistakenly dispatch the first two URLs to the '^foo$' action. +So Catalyst would never mistakenly dispatch the first two URLs to the +'^foo$' action. -=head4 B +=head4 Parameter Processing -Parameters are handled with methods in the L -class. The C method is functionally equivalent to the C -method of C and can be used in modules that require this. +Parameters passed in the URL query string are handled with methods in +the L class. The C method is functionally +equivalent to the C method of C and can be used in +modules that require this. # http://localhost:3000/catalog/view/?category=hardware&page=3 my $category = $c->req->param('category'); @@ -503,13 +530,22 @@ method of C and can be used in modules that require this. =head3 Flow Control -You control the application flow with the C method, which accepts the -key of an action to execute. +You control the application flow with the C method, which +accepts the key of an action to execute. This can be an action in the +same or another Catalyst controller, or a Class name, optionally +followed by a method name. After a C, the control flow will +return to the method from which the C was issued. + +A C is similar to a method call. The main differences are that +it wraps the call in an C to allow exception handling; it +automatically passes along the context object (C<$c> or C<$context>); +and it allows profiling of each call (displayed in the log with +debugging enabled). sub hello : Global { my ( $self, $c ) = @_; $c->stash->{message} = 'Hello World!'; - $c->forward('check_message'); + $c->forward('check_message'); # $c is automatically included } sub check_message : Private { @@ -522,16 +558,40 @@ key of an action to execute. my ( $self, $c ) = @_; $c->res->output( $c->stash->{message} ); } + +A C does not create a new request, so your request +object (C<$c-Ereq>) will remain unchanged. This is a +key difference between using C and issuing a +redirect. + +You can pass new arguments to a C by adding them +in an anonymous array. In this case C<$c-Ereq-Eargs> +will be changed for the duration of the C only; upon +return, the original value of C<$c-Ereq-Eargs> will +be reset. + + sub hello : Global { + my ( $self, $c ) = @_; + $c->stash->{message} = 'Hello World!'; + $c->forward('check_message',[qw/test1/]); + # now $c->req->args is back to what it was before + } + + sub check_message : Private { + my ( $self, $c ) = @_; + my $first_argument = $c->req->args[0]; # now = 'test1' + # do something... + } -As you can see from these examples, you can just use the method name as long as -you are referring to methods in the same controller. If you want to forward to a -method in another controller, or the main application, you will have to refer to -the method by absolute path. +As you can see from these examples, you can just use the method name as +long as you are referring to methods in the same controller. If you want +to forward to a method in another controller, or the main application, +you will have to refer to the method by absolute path. $c->forward('/my/controller/action'); - $c->forward('/default'); + $c->forward('/default'); # calls default in main application -You can also forward to classes and methods. +Here are some examples of how to forward to classes and methods. sub hello : Global { my ( $self, $c ) = @_; @@ -540,7 +600,7 @@ You can also forward to classes and methods. sub bye : Global { my ( $self, $c ) = @_; - $c->forward('MyApp::M::Hello'); + $c->forward('MyApp::M::Hello'); # no method: will try 'process' } package MyApp::M::Hello; @@ -555,9 +615,12 @@ You can also forward to classes and methods. $c->res->output('Goodbye World!'); } -Note that C returns to the calling action and continues processing -after the action finishes. Catalyst will automatically try to call process() if -you omit the method. +Note that C returns to the calling action and continues +processing after the action finishes. If you want all further processing +in the calling action to stop, use C instead, which will execute +the Ced action and not return to the calling sub. In both cases, +Catalyst will automatically try to call process() if you omit the +method. =head3 Components @@ -577,11 +640,11 @@ class structure and some common class methods like C and C 1; -You don't have to C or otherwise register Models, Views, and Controllers. -Catalyst automatically discovers and instantiates them when you call C in -the main application. All you need to do is put them in directories named for -each Component type. Notice that you can use some very terse aliases for each -one. +You don't have to C or otherwise register Models, Views, and +Controllers. Catalyst automatically discovers and instantiates them +when you call C in the main application. All you need to do is +put them in directories named for each Component type. Notice that you +can use some very terse aliases for each one. =over 4 @@ -634,12 +697,12 @@ process/)>. $c->forward('MyApp::V::TT'); } -You normally render templates at the end of a request, so it's a perfect use for -the global C action. +You normally render templates at the end of a request, so it's a perfect +use for the global C action. Also, be sure to put the template under the directory specified in -C<$c-Econfig-E{root}>, or you'll be forced to look at our eyecandy debug -screen. ;) +C<$c-Econfig-E{root}>, or you'll be forced to look at our +eyecandy debug screen. ;) =head4 Models @@ -707,8 +770,41 @@ pass data to your templates. 1; + # Then, in a TT template: The id is [% item.data %] +Models do not have to be part of your Catalyst application; you +can always call an outside module that serves as your Model: + + # in a Controller + sub list : Local { + my ( $self, $c ) = @_; + $c->stash->{template} = 'list.tt'; + use Some::Outside::CDBI::Module; + my @records = Some::Outside::CDBI::Module->retrieve_all; + $c->stash->{records} = \@records; + } + +But by using a Model that is part of your Catalyst application, you gain +several things: you don't have to C each component, Catalyst will +find and load it automatically at compile-time; you can C to +the module, which can only be done to Catalyst componenents; and only +Catalyst components can be fetched with +C<$c-Ecomp('MyApp::M::SomeModel')>. + +Happily, since many people have existing Model classes that they +would like to use with Catalyst (or, conversely, they want to +write Catalyst models that can be used outside of Catalyst, e.g. +in a cron job), it's trivial to write a simple component in +Catalyst that slurps in an outside Model: + + package MyApp::M::Catalog; + use base qw/Catalyst::Base Some::Other::CDBI::Module::Catalog/; + 1; + +and that's it! Now C is part of your +Cat app as C. + =head4 Controllers Multiple controllers are a good way to separate logical domains of your