[ Index ]
 

Code source de PHPonTrax 2.6.6-svn

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/doc/tutorials/PHPonTrax/ -> ActionController.cls (source)

   1  <refentry id="{@id}" revision="$Id: ActionController.cls 199 2006-05-05 01:52:43Z haas $">
   2   <refnamediv>
   3    <refname>ActionController</refname>
   4    <refpurpose></refpurpose>
   5   </refnamediv>
   6   <refsynopsisdiv>
   7    <author>
   8     Walt Haas
   9     <authorblurb>
  10      {@link mailto:haas@xmission.com haas@xmission.com}
  11     </authorblurb>
  12    </author>
  13   </refsynopsisdiv>
  14   {@toc}
  15   <refsect1 id="{@id intro}">
  16    <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>
  27   </refsect1>
  28   <refsect1 id="{@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>
 189  router->connect('',array(':controller' => 'home'));
 190  router->connect('product\?.*',
 191                  array(':controller' => 'catalog', ':action' => 'find'));
 192  router->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 id="{@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, and any
 215     parameters and their values are stored in
 216     {@link ActionController::action_params}.
 217     First file <literal>app/controllers/application.php</literal> is
 218     loaded if it exists. This file contains the definition of the
 219     {@link ApplicationController} class, which extends
 220     <literal>ActionController</literal>.
 221     <literal>ApplicationController</literal> contains properties and
 222     methods used by all the controller classes, which should extend
 223     <literal>ApplicationController</literal> .
 224     Then the controller name is used to find the file and class
 225     containing the selected controller.  By Trax naming conventions, 
 226     if the controller name is
 227     <arg choice="tute-comment">controller&nbsp;name</arg>
 228     then the controller file name is
 229     <arg choice="tute-comment">controller_name</arg><literal>_controller.php</literal>
 230     and the controller class name is
 231     <arg choice="tute-comment">ControllerName</arg> .  So for a
 232     "catalog&nbsp;item" controller, the controller file name is
 233     <literal>catalog_item_controller</literal> and the controller class
 234     name is <literal>CatalogItem</literal>.
 235     The controller file is loaded and a new object of the controller
 236     class is created.
 237    </para>
 238  
 239    <para>
 240     Next any needed helper files are loaded.  Helper files contain PHP
 241     code which helps prepare the output of an action method for
 242     viewing. If file
 243     <literal>application_helper.php</literal> exists, it is loaded.
 244     <literal>application_helper.php</literal> contains
 245     helpers that apply to every controller in the application.
 246     Then the controller-specific helper file
 247     <arg choice="tute-comment">controller_name</arg><literal>_helper.php</literal>
 248     is loaded if it exists.  Finally any extra helper files, as
 249     specified by calls to {@link ActionController::add_helper()}, are
 250     loaded.
 251    </para>
 252  
 253    <para>
 254     When controller and helper files have been loaded, the before
 255     filters are executed (<important>FIXME:</important> We should check
 256     return but don't).  Next the controller object is tested for the
 257     presence of a method with the name of the action as determined from
 258     the URL. If such a method exists, it is called; if 
 259     no such method exists, then the controller object is tested
 260     for the presence of a method named <literal>index()</literal>.
 261     If such a method exists it is called, otherwise the request fails
 262     with 404&nbsp;Unknown&nbsp;action. If an action method was found
 263     and called, the after filters are executed.
 264    </para>
 265  
 266    <refsect2 id="{@id helpers}">
 267     <title>Helper Loading</title>
 268     <para>Helpers are classes that provide view logic.  They exist to
 269      hold view logic that would otherwise need to be added to a
 270      template or controller.  Helper services that are applicable to
 271      the entire application go into
 272      <literal>application_helper.php</literal>, while
 273      controller-specific helper functions go into a helper file named
 274      after the controller, as 
 275      <arg choice="tute-comment">controller_name</arg><literal>_helper.php</literal> 
 276      . Helper classes are written as subclasses of class {@link Helpers},
 277      which has a number of methods widely used by helper
 278      subclasses.  You can add a helper to an
 279      <literal>ActionController</literal> object by calling its
 280      {@link ActionController::add_helper() add_helper()} 
 281      method, passing the name of the helper as an argument.
 282     </para>
 283  
 284     <para>
 285      A number of predefined helper classes are distributed with Trax:
 286      <itemizedlist>
 287       <listitem>{@link ActiveRecordHelper}</listitem>
 288       <listitem>{@link AssetTagHelper}</listitem>
 289       <listitem>{@link DateHelper}</listitem>
 290       <listitem>{@link FormHelper}</listitem>
 291       <listitem>{@link FormTagHelper}</listitem>
 292       <listitem>{@link JavaScriptHelper}</listitem>
 293       <listitem>{@link UrlHelper}</listitem>
 294      </itemizedlist>
 295      These classes are <important>not</important> automatically loaded,
 296      you have to load them explicitly.
 297     </para>
 298     <para></para>
 299    </refsect2>
 300  
 301    <refsect2 id="{@id filters}">
 302     <title>Filters</title>
 303  
 304     <para>Filters enable controllers to run shared pre and post
 305      processing code for its actions. These filters can be used to do
 306      authentication, caching, or auditing before the intended action is
 307      performed. Or to do localization or output compression after the
 308      action has been performed.</para>
 309  
 310     <para>Filters have access to the request, response, and all the
 311      instance variables set by other filters in the chain or by the
 312      action (in the case of after filters). Additionally, it's possible
 313      for a pre-processing <samp>before_filter</samp> to halt the processing
 314      before the intended action is processed by returning false or
 315      performing a redirect or render. (FIXME: we don't implement this)
 316      This is especially useful for
 317      filters like authentication where you're not interested in
 318      allowing the action to be  performed if the proper credentials are
 319      not in order.</para>
 320  
 321     <refsect3 id="{@id filter_inherit}">
 322      <title>Filter inheritance</title>
 323  
 324      <para>Controller inheritance hierarchies share filters downwards, but
 325       subclasses can also add new filters without affecting the
 326       superclass. For example:</para>
 327  
 328      <example>
 329  class BankController extends ActionController
 330  {
 331      $this->before_filter = audit();
 332  
 333      private function audit() {
 334          // record the action and parameters in an audit log
 335      }
 336  }
 337  
 338  class VaultController extends BankController
 339  {
 340      $this->before_filter = verify_credentials();
 341  
 342      private function verify_credentials() {
 343          // make sure the user is allowed into the vault
 344      }
 345  }
 346      </example>
 347  
 348      <para>Now any actions performed on the BankController will have the
 349       audit method called before. On the VaultController, first the
 350       audit method is called, then the verify_credentials method. If the
 351       audit method returns false, then verify_credentials and the
 352       intended action are never called.  <important>FIXME:
 353       This is currently broken.</important></para>
 354      </refsect3>
 355  
 356      <refsect3 id="{@id filter_types}">
 357       <title>Filter types</title>
 358  
 359       <para>A filter can take one of three forms: method reference
 360        (symbol), external class, or inline method (proc). The first is the
 361        most common and works by referencing a protected or private method
 362        somewhere in the inheritance hierarchy of the controller by use of
 363        a symbol. In the bank example above, both BankController and
 364        VaultController use this form.</para>
 365  
 366       <para>Using an external class makes for more easily reused generic
 367        filters, such as output compression. External filter classes are
 368        implemented by having a static +filter+ method on any class and
 369        then passing this class to the filter method. Example:</para>
 370   
 371       <example>
 372  class OutputCompressionFilter
 373  {
 374      static functionfilter(controller) {
 375          controller.response.body = compress(controller.response.body)
 376      }
 377  }
 378  
 379  class NewspaperController extends ActionController
 380  {
 381      $this->after_filter = OutputCompressionFilter;
 382  }
 383       </example>
 384  
 385       <para>The filter method is passed the controller instance and is
 386        hence granted access to all aspects of the controller and can
 387        manipulate them as it sees fit.</para>
 388  
 389       <para>The inline method (using a proc) can be used to quickly do
 390        something small that doesn't require a lot of explanation.  Or
 391        just as a quick test. It works like this:</para>
 392   
 393       <example>
 394  class WeblogController extends ActionController
 395  {
 396      before_filter { |controller| false if controller.params["stop_action"] }
 397  }
 398       </example>
 399  
 400       <para>As you can see, the block expects to be passed the controller
 401        after it has assigned the request to the internal variables.  This
 402        means that the block has access to both the request and response
 403        objects complete with convenience methods for params, session,
 404        template, and assigns. Note: The inline method doesn't strictly
 405        have to be a block; any object that responds to call and returns 1
 406        or -1 on arity will do (such as a Proc or an Method object).</para>
 407      </refsect3>
 408  
 409      <refsect3 id="{@id filter_skip}">
 410       <title>Filter chain skipping</title>
 411  
 412       <para>Some times its convenient to specify a filter chain in a
 413        superclass that'll hold true for the majority of the subclasses,
 414        but not necessarily all of them. The subclasses that behave in
 415        exception can then specify which filters they would like to be
 416        relieved of. Examples</para> 
 417  
 418       <example>
 419  class ApplicationController extends ActionController
 420  {
 421      $this->before_filter = authenticate();
 422  }
 423  
 424  class WeblogController extends ApplicationController
 425  {
 426      // will run the authenticate() filter
 427  }
 428       </example>
 429      </refsect3>
 430  
 431      <refsect3 id="{@id filter_conditions}">
 432       <title>Filter conditions</title>
 433  
 434       <para>Filters can be limited to run for only specific
 435        actions. This can be expressed either by listing the actions to
 436        exclude or the actions to include when executing the
 437        filter. Available conditions are +:only+ or +:except+, both of
 438        which accept an arbitrary number of method references. For
 439        example:</para> 
 440  
 441       <example>
 442  class Journal extends ActionController
 443  {
 444      // only require authentication if the current action is edit or delete
 445      before_filter :authorize, :only => [ :edit, :delete ]
 446      
 447      private function authorize() {
 448          // redirect to login unless authenticated
 449      }
 450  }
 451       </example>
 452   
 453       <para>When setting conditions on inline method (proc) filters the
 454        condition must come first and be placed in parentheses.</para>
 455   
 456      <example>
 457  class UserPreferences extends ActionController
 458  {
 459      before_filter(:except => :new) { ? some proc ... }
 460      ...
 461  }
 462      </example>
 463     </refsect3>
 464    </refsect2>
 465   </refsect1>
 466   <refsect1 id="{@id render}">
 467    <title>Redirect Browser or Render Output</title>
 468  
 469    <para>After the controller object's action method has returned to
 470     <literal>ActionController::process_route()</literal> and the after
 471     filters have been executed, the controller object is examined for
 472     a property named <literal>redirect_to</literal>.  If this
 473     property exists and has a value, it means that the action method
 474     has decided to redirect the user's browser to a different URL.  The
 475     value of the <literal>redirect_to</literal> property is passed to
 476     {@link ActionController::redirect_to() <literal>redirect_to()</literal>}
 477     which outputs a header redirecting the browser, then calls
 478     {@link http://www.php.net/manual/en/function.exit.php exit} .</para>
 479  
 480    <para>
 481     If the action didn't redirect the browser, it should have provided
 482     output to send to the browser.  This is in the form of explicit
 483     output produced by calls to
 484     {@link http://www.php.net/manual/en/function.echo.php echo},
 485     {@link http://www.php.net/manual/en/function.print.php print} or
 486     {@link http://www.php.net/manual/en/function.printf.php printf} ,
 487     plus any properties of the controller object that are referenced in
 488     the layout. <literal>ActionController::process_route()</literal>
 489     collects all output produced by the controller's action method
 490     in the output buffer, for presentation within a layout.
 491    </para>
 492  
 493    <para>
 494     If the controller object has a property
 495     <literal>render_text</literal> which contains a string, then this
 496     string is sent directly to the browser and all output and view
 497     files are ignored.
 498    </para>
 499  
 500    <para>
 501     If <literal>render_text</literal> is undefined or empty, then the
 502     saved output of the controller's action method is to be rendered.
 503     A <important>view file</important> determined by the action is
 504     found and included.  The view file for an action is
 505     <literal>app/views/</literal><arg choice="tute-comment">controller_name/action_name</arg><literal>.phtml</literal> .
 506     This file contains HTML, which goes to the output buffer after the
 507     action method's output.  The output buffer is now assigned to
 508     $content_for_layout.  Finally the layout file is loaded.  The
 509     view file and layout file both contain HTML with
 510     {@link http://www.php.net/manual/en/language.basic-syntax.php embedded PHP}
 511     expressions to present action method output to the user.
 512    </para>
 513   </refsect1>
 514  <!--
 515  Local variables:
 516  mode: xml
 517  c-basic-offset: 1
 518  indent-tabs-mode: nil
 519  End:
 520  -->
 521  </refentry>


Généré le : Sun Feb 25 20:04:38 2007 par Balluche grâce à PHPXref 0.7