Show
Ignore:
Timestamp:
03/13/06 21:10:15 (6 years ago)
Author:
haas
Message:

ActionController? doc done

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/trax/tutorials/PHPonTrax/ActionController.cls

    r159 r174  
    1515 <refsect1 id="{@id intro}"> 
    1616  <title>Introduction</title> 
     17  <para>The {@link ActionController} base class does the 
     18  following:</para> 
     19  <orderedlist> 
     20    <listitem>Accepts a URL as input</listitem> 
     21    <listitem>Translates the URL into a controller and action</listitem> 
     22    <listitem>Creates the indicated controller object (which is a subclass 
     23      of ActionController) and calls its action method</listitem> 
     24    <listitem>Redirects to another URL or renders the output of the 
     25    action method</listitem>  
     26  </orderedlist> 
    1727 </refsect1> 
    18  <refsect1 id="{@id filters}"> 
    19   <title>Filters</title> 
     28 <refsect1 is="{@id url}"> 
     29  <title>URL Processing</title> 
     30 
     31  <para> 
     32   When Apache receives an HTTP request addressed to a Trax 
     33   application, 
     34{@link http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html Apache mod_rewrite} 
     35   is invoked and rewrites the request to invoke Trax file 
     36   <literal>dispatch.php</literal>.  At this time the URL which was 
     37   input to the rewrite rules is in 
     38{@link http://www.php.net/manual/en/reserved.variables.php#reserved.variables.server $_SERVER}['REDIRECT_URL'].   
     39   <literal>dispatch.php</literal> creates a new {@link Dispatcher} 
     40   object and calls its  
     41   {@link Dispatcher::dispatch() dispatch()} method. dispatch() 
     42   restores the state of the session identified by a cookie in the 
     43   request, or creates a session if none exists.  Then it creates a 
     44   new ActionController object and calls its 
     45   {@link ActionController::process_route() <literal>process_route()</literal>}  
     46   method.  
     47  </para> 
     48 
     49  <para> 
     50   The word "route" is used in Trax to describe a rule which 
     51   translates some URL into a particular controller object and method. 
     52   When <literal>process_route()</literal> receives control, it calls 
     53   {@link ActionController::recognize_route() recognize_route()} to 
     54   parse the URL into controller, action and id 
     55   components. recognize_route() calls 
     56   {@link ActionController::load_router() load_router()} to load the 
     57   "routing table", which is a list of one or more 
     58   <literal>$router->connect()</literal> calls, from 
     59   {@link routes.php <literal>config/routes.php</literal>}.   
     60   This list of calls define the rules for translating a URL into a 
     61   controller and action. 
     62  </para> 
     63 
     64  <para> 
     65   The translation rules work as follows:  Starting with the first 
     66   rule in <literal>routes.php</literal>, each rule is tested against 
     67   the URL to see  
     68   whether the rule matches.  If a rule does not match, then the next 
     69   rule in the table is tested in turn, until a rule matches or the 
     70   table is exhausted.  If no matching rule is found, 
     71   recognize_route() tests the last route in the table to see whether 
     72   it is the default route <literal>:controller/:action/:id</literal> 
     73   .  If the last route is the default route, then 
     74   <literal>recognize_route()</literal> 
     75   returns it as a match, even if it does not in fact match.  But if 
     76   there is no matching route and the last route in the table is not 
     77   the default route, then recognize_route() returns 'failure' which is 
     78   equivalent to HTTP code '404&nbsp;Not&nbsp;found'. 
     79  </para> 
     80 
     81  <para> 
     82   Each entry in the route table contains two parts: 
     83   <orderedlist> 
     84    <listitem> 
     85     A <important>path</important>, which is a character string to 
     86     test against the URL. 
     87    </listitem> 
     88    <listitem> 
     89     <important>Parameters</important>, which are not tested against 
     90     the URL and aren't involved unless the 
     91     <important>path</important> part of the entry matches the URL. 
     92     <important>Parameters</important> are optional (and frequently 
     93     omitted). 
     94    </listitem> 
     95   </orderedlist> 
     96   A <important>path</important> is a series of substrings separated 
     97   by '/' (forward slash) characters.  Each of these substrings can 
     98   contain any character except '/'.  The <important>path</important> 
     99   does not begin or end with '/'.  A substring may not be the null 
     100   (no characters) string, but it is legal for the entire 
     101   path to be the null string. Each substring is one of the following: 
     102   <itemizedlist> 
     103    <listitem><literal>:controller</literal></listitem> 
     104    <listitem><literal>:action</literal></listitem> 
     105    <listitem><literal>:id</literal></listitem> 
     106    <listitem>A 
     107     {@link http://www.php.net/manual/en/ref.pcre.php Perl regular expression} 
     108     that does not begin with ':' (colon)</listitem> 
     109   </itemizedlist> 
     110   The following are legal <important>path</important> values: 
     111   <itemizedlist> 
     112    <listitem><literal>:controller/:action/:id</literal> 
     113     This is the default <important>path</important>. It matches URLs 
     114     like <literal>word1/word2/word3</literal></listitem> 
     115    <listitem><literal>catalog/product/:action/:id</literal> 
     116     Remember that <literal>catalog</literal> is a Perl regular 
     117     expression that matches <literal>catalog</literal>, and 
     118     <literal>product</literal> is a Perl regular expression that 
     119     matches <literal>product</literal>, so this 
     120     <important>path</important> matches URLs like  
     121     <literal>catalog/product/word1/word2</literal></listitem> 
     122    <listitem><literal>''</literal> matches '' (the empty string as a  
     123     <important>path</important> value matches the empty string as a 
     124     URL).</listitem> 
     125    <listitem><literal>member/name=.*</literal> matches URLs like 
     126     <literal>member/name=</literal> or 
     127     <literal>member/name=Tom.Jones</literal> or 
     128     <literal>member/name=Smith,J/since=1987/type=full</literal> etc. 
     129    </listitem> 
     130   </itemizedlist> 
     131   <literal>:controller</literal>, <literal>:action</literal> and 
     132   <literal>:id</literal> may each appear at most once in a  
     133   <important>path</important>. 
     134  </para> 
     135 
     136  <para> 
     137   After the URL has been matched to a <important>path</important>, 
     138   the next step is to extract the name of the controller and action 
     139   to be invoked on this URL.  These must be valid names in the PHP 
     140   language consisting only of lower-case alphameric characters and 
     141   '_' (underscore), because the controller name will translate 
     142   directly into a file name and a class name, and the action name 
     143   will be used as the name of a method in that class.  The controller 
     144   and action names come from the route that matches the URL. 
     145  </para> 
     146 
     147  <para> 
     148   There are two places that a route can specify a controller or 
     149   action name: as part of the <important>path</important>, or in the  
     150   <important>parameters</important>.  The 
     151   <important>parameters</important> are the optional second part of a 
     152   route.  The value of <important>parameters</important> is an array 
     153   with key values that may be <literal>:controller</literal> or 
     154   <literal>:action</literal>.  The following are legal 
     155   <important>parameters</important> values: 
     156   <itemizedlist> 
     157    <listitem><literal>array(':controller' => 
     158     'new_product')</literal></listitem>  
     159    <listitem><literal>array(':action' => 'enter')</literal></listitem> 
     160    <listitem><literal>array(':controller' => 'membership', ':action 
     161     => 'new')</literal></listitem>  
     162   </itemizedlist>     
     163  </para> 
     164 
     165  <para> 
     166   When a URL matches a route, the controller name is extracted as 
     167   follows:  First, if the <important>parameters</important> array 
     168   exists and has an element whose key is 
     169   <literal>:controller</literal>, then the value of that element is 
     170   used as the controller name.  If no <literal>:controller</literal> 
     171   is specified by the <important>parameters</important>, then the 
     172   <important>path</important> is tested for a substring whose value 
     173   is <literal>:controller</literal>.  If found, then the part of the 
     174   URL which matched that substring is used as the controller value. 
     175   A controller value must be specified by either the 
     176   <important>parameters</important> or the 
     177   <important>path</important>.  The action name is extracted by the 
     178   same process, substituting <literal>:action</literal> for  
     179   <literal>:controller</literal>.  If the 
     180   <important>path</important> has a substring <literal>:id</literal>, 
     181   then the part of the URL which matched that substring is forced to 
     182   lower case and the result assigned to 
     183   <literal>$_REQUEST['id']</literal>. 
     184  </para> 
     185 
     186  <para> 
     187   If <literal>routes.php</literal> contains the following: 
     188   <example> 
     189router->connect('',array(':controller' => 'home')); 
     190router->connect('product\?.*', 
     191                array(':controller' => 'catalog', ':action' => 'find')); 
     192router->connect(':controller/:action/:id'); 
     193   </example> 
     194   Then URLs will match routes as follows: 
     195   <itemizedlist>     
     196    <listitem>URL <literal>''</literal> (no characters) will select 
     197     controller <literal>home</literal>, action not specified. 
     198    </listitem> 
     199    <listitem>URL <literal>product?item=4317</literal> will select 
     200     controller <literal>catalog</literal>, action 
     201     <literal>find</literal> 
     202    </listitem> 
     203    <listitem>URL <literal>cart/add/4317</literal> will select 
     204     controller <literal>cart</literal>, action <literal>add</literal> 
     205    </listitem> 
     206   </itemizedlist>     
     207  </para> 
     208 
     209 </refsect1> 
     210 <refsect1 is="{@id action}"> 
     211  <title>Action Call</title> 
     212  <para>When the names of the controller and action have been 
     213   successfully determined from the URL, the associated filesystem 
     214   paths are constructed and relevant files are loaded. 
     215   First file <literal>app/controllers/application.php</literal> is 
     216   loaded if it exists. This file contains the definition of the 
     217   {@link ApplicationController} class, which extends 
     218   <literal>ActionController</literal>. 
     219   <literal>ApplicationController</literal> contains properties and 
     220   methods used by all the controller classes, which should extend 
     221   <literal>ApplicationController</literal> . 
     222   Then the controller name is used to find the file and class 
     223   containing the selected controller.  By Trax naming conventions,  
     224   if the controller name is 
     225   <arg choice="tute-comment">controller&nbsp;name</arg> 
     226   then the controller file name is 
     227   <arg choice="tute-comment">controller_name</arg><literal>_controller.php</literal> 
     228   and the controller class name is 
     229   <arg choice="tute-comment">ControllerName</arg> .  So for a 
     230   "catalog&nbsp;item" controller, the controller file name is 
     231   <literal>catalog_item_controller</literal> and the controller class 
     232   name is <literal>CatalogItem</literal>. 
     233   The controller file is loaded and a new object of the controller 
     234   class is created. 
     235  </para> 
     236 
     237  <para> 
     238   Next any needed helper files are loaded.  Helper files contain PHP 
     239   code which helps prepare the output of an action method for 
     240   viewing. If file 
     241   <literal>application_helper.php</literal> exists, it is loaded. 
     242   <literal>application_helper.php</literal> contains 
     243   helpers that apply to every controller in the application. 
     244   Then the controller-specific helper file 
     245   <arg choice="tute-comment">controller_name</arg><literal>_helper.php</literal> 
     246   is loaded if it exists.  Finally any extra helper files, as 
     247   specified by calls to {@link ActionController::add_helper()}, are 
     248   loaded. 
     249  </para> 
     250 
     251  <para> 
     252   When controller and helper files have been loaded, the before 
     253   filters are executed (<important>FIXME:</important> We should check 
     254   return but don't).  Next the controller object is tested for the 
     255   presence of a method with the name of the action as determined from 
     256   the URL. If such a method exists, it is called; if  
     257   no such method exists, then the controller object is tested 
     258   for the presence of a method named <literal>index()</literal>. 
     259   If such a method exists it is called, otherwise the request fails 
     260   with 404&nbsp;Unknown&nbsp;action. If an action method was found 
     261   and called, the after filters are executed. 
     262  </para> 
     263 
     264  <refsect2 id="{@id helpers}"> 
     265   <title>Helper Loading</title> 
     266   <para>Helpers are classes that provide view logic.  They exist to 
     267    hold view logic that would otherwise need to be added to a 
     268    template or controller.  Helper services that are applicable to 
     269    the entire application go into 
     270    <literal>application_helper.php</literal>, while 
     271    controller-specific helper functions go into a helper file named 
     272    after the controller, as  
     273    <arg choice="tute-comment">controller_name</arg><literal>_helper.php</literal>  
     274    . Helper classes are written as subclasses of class {@link Helpers}, 
     275    which has a number of methods widely used by helper 
     276    subclasses.  You can add a helper to an 
     277    <literal>ActionController</literal> object by calling its 
     278    {@link ActionController::add_helper() add_helper()}  
     279    method, passing the name of the helper as an argument. 
     280   </para> 
     281 
     282   <para> 
     283    A number of predefined helper classes are distributed with Trax: 
     284    <itemizedlist> 
     285     <listitem>{@link ActiveRecordHelper}</listitem> 
     286     <listitem>{@link AssetTagHelper}</listitem> 
     287     <listitem>{@link DateHelper}</listitem> 
     288     <listitem>{@link FormHelper}</listitem> 
     289     <listitem>{@link FormTagHelper}</listitem> 
     290     <listitem>{@link JavaScriptHelper}</listitem> 
     291     <listitem>{@link UrlHelper}</listitem> 
     292    </itemizedlist> 
     293    These classes are <important>not</important> automatically loaded, 
     294    you have to load them explicitly. 
     295   </para> 
     296   <para></para> 
     297  </refsect2> 
     298 
     299  <refsect2 id="{@id filters}"> 
     300   <title>Filters</title> 
    20301 
    21302   <para>Filters enable controllers to run shared pre and post 
     
    30311    for a pre-processing <samp>before_filter</samp> to halt the processing 
    31312    before the intended action is processed by returning false or 
    32     performing a redirect or render.  This is especially useful for 
     313    performing a redirect or render. (FIXME: we don't implement this) 
     314    This is especially useful for 
    33315    filters like authentication where you're not interested in 
    34316    allowing the action to be  performed if the proper credentials are 
    35317    not in order.</para> 
    36318 
    37    <refsect2 id="{@id filter_inherit}"> 
     319   <refsect3 id="{@id filter_inherit}"> 
    38320    <title>Filter inheritance</title> 
    39321 
     
    66348     audit method is called, then the verify_credentials method. If the 
    67349     audit method returns false, then verify_credentials and the 
    68      intended action are never called.</para> 
    69     </refsect2> 
    70  
    71     <refsect2 id="{@id filter_types}"> 
     350     intended action are never called.  <important>FIXME: 
     351     This is currently broken.</important></para> 
     352    </refsect3> 
     353 
     354    <refsect3 id="{@id filter_types}"> 
    72355     <title>Filter types</title> 
    73356 
     
    120403      have to be a block; any object that responds to call and returns 1 
    121404      or -1 on arity will do (such as a Proc or an Method object).</para> 
    122     </refsect2> 
    123  
    124     <refsect2 id="{@id filter_skip}"> 
     405    </refsect3> 
     406 
     407    <refsect3 id="{@id filter_skip}"> 
    125408     <title>Filter chain skipping</title> 
    126409 
     
    142425} 
    143426     </example> 
    144     </refsect2> 
    145  
    146     <refsect2 id="{@id filter_conditions}"> 
     427    </refsect3> 
     428 
     429    <refsect3 id="{@id filter_conditions}"> 
    147430     <title>Filter conditions</title> 
    148431 
     
    169452      condition must come first and be placed in parentheses.</para> 
    170453  
    171    <example> 
     454    <example> 
    172455class UserPreferences extends ActionController 
    173456{ 
     
    175458    ... 
    176459} 
    177   </example> 
     460    </example> 
     461   </refsect3> 
    178462  </refsect2> 
     463 </refsect1> 
     464 <refsect1 id="{@id render}"> 
     465  <title>Redirect Browser or Render Output</title> 
     466 
     467  <para>After the controller object's action method has returned to 
     468   <literal>ActionController::process_route()</literal> and the after 
     469   filters have been executed, the controller object is examined for 
     470   a property named <literal>redirect_to</literal>.  If this 
     471   property exists and has a value, it means that the action method 
     472   has decided to redirect the user's browser to a different URL.  The 
     473   value of the <literal>redirect_to</literal> property is passed to 
     474   {@link ActionController::redirect_to() <literal>redirect_to()</literal>} 
     475   which outputs a header redirecting the browser, then calls 
     476   {@link http://www.php.net/manual/en/function.exit.php exit} .</para> 
     477 
     478  <para> 
     479   If the action didn't redirect the browser, it should have provided 
     480   output to send to the browser.  This is in the form of explicit 
     481   output produced by calls to 
     482   {@link http://www.php.net/manual/en/function.echo.php echo}, 
     483   {@link http://www.php.net/manual/en/function.print.php print} or 
     484   {@link http://www.php.net/manual/en/function.printf.php printf} , 
     485   plus any properties of the controller object that are referenced in 
     486   the layout. <literal>ActionController::process_route()</literal> 
     487   collects all output produced by the controller's action method 
     488   in the output buffer, for presentation within a layout. 
     489  </para> 
     490 
     491  <para> 
     492   If the controller object has a property 
     493   <literal>render_text</literal> which contains a string, then this 
     494   string is sent directly to the browser and all output and view 
     495   files are ignored. 
     496  </para> 
     497 
     498  <para> 
     499   If <literal>render_text</literal> is undefined or empty, then the 
     500   saved output of the controller's action method is to be rendered. 
     501   A <important>view file</important> determined by the action is 
     502   found and included.  The view file for an action is 
     503   <literal>app/views/</literal><arg choice="tute-comment">controller_name/action_name</arg><literal>.phtml</literal> . 
     504   This file contains HTML, which goes to the output buffer after the 
     505   action method's output.  The output buffer is now assigned to 
     506   $content_for_layout.  Finally the layout file is loaded.  The 
     507   view file and layout file both contain HTML with 
     508   {@link http://www.php.net/manual/en/language.basic-syntax.php embedded PHP} 
     509   expressions to present action method output to the user. 
     510  </para> 
    179511 </refsect1> 
    180512<!--