Action Controller

Action Controller 过滤器

对于actions来说,过滤器可以使controllers运行共享的pre并且布置处理代码。在将要执行的action之前,这些过滤器可以用来作authentication,caching,或者auditing 。或者在action执行之后,用来定位或输出压缩。

过滤器访问request,response,和在链中的其他过滤器或者action(in the case of after filters)中的所有实例化的变量。另外,使前处理beforeFilter能够停止处理过程, 在执行将要执行的action时,通过执行返回错误值或者执行redirect或者render。 这个对于像authentication等特别有用,如果proper credentials没有在队列中,你也不用关心允许那个action运行。

Filter遗传

Controller遗传了分级结构,共享了下面的filters,但是子类也可以添加新的filters,并不会影响父类。For example:

class BankController extends AkActionController 
{
    function __construct()
    {
        $this->beforeFilter('_audit');
    }
 
    function _audit(&$controller)
    {
        // record the action and parameters in an audit log  
    }
}
 
class VaultController extends BankController 
{
    function __construct()
    {
        $this->beforeFilter('_verifyCredentials');
    }
 
    function _verifyCredentials(&$controller)
    {
        // make sure the user is allowed into the vault
    }
}

现在在BankController中的任何一个actions执行之前,将会调用audit method。在VaultController中, 首先audit method被调用, is called,然后是_verifyCredentials method。如果_audit method返回值为false,那么 _verifyCredentials和intended action将永远不会被执行。

Filter类型

filter能采用三种类型的一个: method reference, external class,或者inline method。第一个是最常见的,通过引用一个方法使之工作,在controller的遗传等级中通过使用方法的名字。 . 在上面的例子中,BankController和VaultController都使用了这个类型。

使用外部类可以更容易的重用一般的filters,例如output compression。外部的filter classes在任何类上,通过一个静态的filter方法来执行。然后从这个类去filter method。 Example:

class OutputCompressionFilter
{
    function filter(&$controller)
    {
        $controller->response->body = compress($controller->response->body);
    }
}
 
class NewspaperController extends AkActionController 
{
    function __construct()
    {
        $this->afterFilter(new OutputCompressionFilter());
    }
}

这个filter method通过之后,controller的实例并且能够访问controller的各个方面,并且能够操作他们。

Filter的排序链

使用beforeFilterafterFilter在已存在的链中添加指定的filters。一般来说这不错,但是有些时候你必须注意执行filters的顺序。当那个情形时,你可以使用 prependBeforeFilterprependAfterFilter。这些Filters会被追加到各自的链的开始,在rest之前执行他们。 For example:

class ShoppingController extends AkActionController 
{
    function __construct()
    {
        $this->beforeFilter('verifyOpenShop');
    }
}
 
 
class CheckoutController extends AkActionController 
{
    function __construct()
    {
        $this->prependBeforeFilter('ensureItemsInCart', 'ensureItemsInStock');
    }
}

CheckoutController的filter链现在是'ensureItemsInCart, ensureItemsInStock, verifyOpenShop''。所以任何一个filters返回值为false,如果商店没有开门,我们永远不能去四周转转。

你也许通过了每个类型复合的filter参数。

filters周围

除了个别的before和after filters的之外,对于指定的对象来说也应该能够处理before and after调用。当你需要before and after之间保持状态的有效性的时候,这是特别有用的。 such as the example of a benchmark filter below:

class WeblogController extends AkActionController 
{
    function __construct()
    {
        $this->aroundFilter(new BenchmarkingFilter());
    }
 
    // Before this action is performed, BenchmarkingFilter->before($controller) is executed
   function index()
   {
   }
    // After this action has been performed, BenchmarkingFilter->after($controller) is executed
}
 
class BenchmarkingFilter
{
    function before(&$controller)
    {
        start_timer();
    }
 
    function after(&$controller)
    {
        stop_timer();
        report_result();   
    }
}

Filter chain skipping

有些时候在父类中指定一个filter chain是非常方便的,他将会为大多数的子类保持真值, 但是不是所有的都需要。子类在意外情况下表现的很好,他们可以指定他们喜欢的filters来释放。 Examples

class ApplicationController extends AkActionController 
{
    function __construct()
    {
        $this->beforeFilter('authenticate');
    }
}
 
class WeblogController extends ApplicationController
{
    // will run the authenticate filter
}
 
class SignupController extends AkActionController 
{
    function __construct()
    {
        $this->skipBeforeFilter('authenticate');
    }
    // will not run the authenticate filter
}

Filter条件

Filters可以被限制在特定的actions中运行。在执行filter时可以通过监听被除外的actions和被包括的actions来清楚的说明。 可用的conditions是only or except, 他们两个both可以接受参考方法的任何数。 For example:

  class Journal extends AkActionController 
  {
      function __construct()
      {   // only require authentication if the current action is edit or delete
          $this->beforeFilter(array('_authorize'=>array('only'=>array('edit','delete')));
      }
 
      function _authorize(&$controller)
      {
        // redirect to login unless authenticated
      }
  }
 
filters-and-verification_cn.txt · Last modified: 2008/07/24 07:45 by liyh