X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FIntro.pod;h=b96b1b9c8630b54d94e57ea9b754f57faac44da5;hb=0cf56dbcd3a060c815aa5e66a67709bb51efd80d;hp=06ea0c16dac7e00c912941b06cdfb67b0c3c6649;hpb=d08ced285005d2a98eb0079b4b4ddad72325e367;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Manual/Intro.pod b/lib/Catalyst/Manual/Intro.pod index 06ea0c1..b96b1b9 100644 --- a/lib/Catalyst/Manual/Intro.pod +++ b/lib/Catalyst/Manual/Intro.pod @@ -43,11 +43,11 @@ control. Catalyst! =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, Johson and -Vlissides, also known as the Gang of Four (GoF). You can also just google it. -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). You +can also just Google it. Many, many web application frameworks are +based on MVC, including all those listed above. =head3 Flexibility @@ -84,7 +84,7 @@ With Catalyst you register your actions and address them directly. For example: sub hello : Global { my ( $self, $context ) = @_; - $context->response->output('Hello World!'); + $context->response->body('Hello World!'); } Now http://localhost:3000/hello prints "Hello World!". @@ -184,7 +184,6 @@ application, load plugins, define application-wide actions, and extend Catalyst. MyApp->config( name => 'My Application', - root => '/home/joeuser/myapp/root', # You can put anything else you want in here: my_configuration_variable => 'something', @@ -192,13 +191,13 @@ application, load plugins, define application-wide actions, and extend Catalyst. sub default : Private { my ( $self, $context ) = @_; - $context->response->output('Catalyst rockz!'); + $context->response->body('Catalyst rockz!'); } 1; -For most applications, Catalyst requires you to define only two config -parameters: +For most applications, Catalyst requires you to define only one config +parameter: =over 4 @@ -206,15 +205,13 @@ parameters: Name of your application. -=item * B - -Path to additional files such as templates, images, or other static data. - =back -However, 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-Econfig-E{$param_name}>. +Optionally, you can specify a B 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-Econfig-E{$param_name}>. =head3 Context @@ -233,7 +230,7 @@ Catalyst developers just call it C<$c>: sub hello : Global { my ( $self, $c ) = @_; - $c->res->output('Hello World!'); + $c->res->body('Hello World!'); } The Context contains several important objects: @@ -261,7 +258,7 @@ query parameters, cookies, uploads, headers, and more. The response is like the request, but contains just response-specific information. - $c->res->output('Hello World'); + $c->res->body('Hello World'); $c->res->status(404); $c->res->redirect('http://oook.de'); @@ -298,7 +295,7 @@ application components. For an example, we return to our 'hello' action: sub show_message : Private { my ( $self, $c ) = @_; - $c->res->output( $c->stash->{message} ); + $c->res->body( $c->stash->{message} ); } Note that the stash should be used only for passing data in an individual @@ -320,10 +317,24 @@ Catalyst supports several types of actions: =item * B + package MyApp::C::My::Controller; sub bar : Path('foo/bar') { } +Literal C actions will act relative to their current namespace. The above +example matches only http://localhost:3000/my/controller/foo/bar. If you start +your path with a forward slash, it will match from the root. Example: + + package MyApp::C::My::Controller; + sub bar : Path('/foo/bar') { } + Matches only http://localhost:3000/foo/bar. + package MyApp::C::My::Controller; + sub bar : Path { } + +By leaving the C definition empty, it will match on the namespace root. +The above code matches http://localhost:3000/my/controller. + =item * B sub bar : Regex('^item(\d+)/order(\d+)$') { } @@ -336,10 +347,27 @@ Regex matches act globally, i.e. without reference to the namespace from which it is called, so that a C method in the C namespace won't match any form of C, C, C, or C unless you explicitly put this in -the regex. +the regex. To achieve the above, you should consider using a C action. + +=item * B -If you use capturing parentheses to extract values within the matching URL (23, -42 in the above example), those values are available in the $c->req->snippets + sub bar : LocalRegex('^widget(\d+)$') { } + +LocalRegex actions act locally. If you were to use C in +C, the above example would match urls like +http://localhost:3000/catalog/widget23. + +If you omit the "C<^>" from your regex, then it will match any depth from the +controller and not immediately off of the controller name. The following example +differes from the above code in that it will match +http://localhost:3000/catalog/foo/widget23 as well. + + package MyApp::Controller::Catalog; + sub bar : LocalRegex('widget(\d+)$') { } + +For both LocalRegex and Regex actions, if you use capturing parentheses to +extract values within the matching URL ("widget23" would capture "23" in the +above example), those values are available in the $c->req->snippets array. If you want to pass arguments at the end of your URL, you must use regex action keys. See L below. @@ -376,10 +404,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 +419,94 @@ 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. + +If C isn't acting how you would expect, look at using a +L C action (with an empty path string). The difference +being that C takes arguments relative from the namespace and +C takes arguments relative from the root. + +=item * B + +C is much like C except that it takes no arguments +and it is weighted slightly higher in the matching process. =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 +514,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 +544,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'); @@ -529,7 +594,7 @@ debugging enabled). sub show_message : Private { my ( $self, $c ) = @_; - $c->res->output( $c->stash->{message} ); + $c->res->body( $c->stash->{message} ); } A C does not create a new request, so your request @@ -580,17 +645,20 @@ Here are some examples of how to forward to classes and methods. sub say_hello { my ( $self, $c ) = @_; - $c->res->output('Hello World!'); + $c->res->body('Hello World!'); } sub process { my ( $self, $c ) = @_; - $c->res->output('Goodbye World!'); + $c->res->body('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. +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 @@ -610,11 +678,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 @@ -649,8 +717,8 @@ inherit from this class: script/myapp_create.pl view TT TT -where the first C tells the script to create a Template Toolkit -view, and the second tells the script that its name should be C.) +where the first C tells the script that the name of the view should +be C, and the second that it should be a Template Toolkit view.) This gives us a process() method and we can now just do $c->forward('MyApp::V::TT') to render our templates. The base class makes @@ -667,12 +735,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 @@ -740,8 +808,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 components; 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 @@ -749,9 +850,9 @@ application. package MyApp::C::Login; - sign-in : Local { } - new-password : Local { } - sign-out : Local { } + sub sign-in : Local { } + sub new-password : Local { } + sub sign-out : Local { } package MyApp::C::Catalog;