也说Solar自定义Filter

@lifeSolar自定义Filter过滤器 一文中讲述了如何在Solar中添加自己的过滤器,讲得很不错。呵呵:), @life@libear 加入Solar 中国 没多长时间,但贡献却非常突出,给Solar 中国 注入了更有活力的思想。

回到正题,本文也是讨论在Solar中自定义Filter,那么为什么要写一篇同样主题的文章呢?看完你就知道了。

讲这个之前我认为有必要先讲一下life提到的自定义Filter如何实现的。那么之前又还要再讲一下Solar_Sql_Model_Record 这个类。
关于这个类,相信大家不会陌生,当我们每次从对象注册表中获取模型目录对象后,再利用模型对象获取的就是Record对象。

01. $this ->_model = Solar_Registry::get( 'model_catalog' );
02. // $this->item就是模型记录对象
03. $this ->item = $this ->_model->currentProducts->fetchNew();
04. $this ->form = $this ->item->newForm( array (
05.              'digs_out' => array ( 'label' => '请输入免单需顶数:' ,),
06.              'discout' => array ( 'label' => '请输入折扣:' , 'invalid' => array ( 'hello, libear' , 'hello, life' )),
07.              'product_id' => array ( 'type' => 'hidden' ,),
08.              'period_id' => array ( 'type' => 'hidden' ,),
09.          ));

这就创建了大家非常熟悉的form对象,之后怎么做大家都知道的。那么filter是在什么时候验证的呢?如何保证Solar能找到我们自定义的Filter呢?

filter事件是在$this->item->save()方法调用的时候触发的,来看代码:在Solar_Sql_Model_Record::save() 方法又调用了Solar_Sql_Model_Record::_save() 方法,在_save()方法中判断当前的保存操作是插入还是更新:

1. // insert or update based on newness
2. if ( $this ->isNew()) {
3.      $this ->_insert();
4. } else {
5.      $this ->_update();
6. }

Solar_Sql_Model_Record::_insert()Solar_Sql_Model_Record::_update() 方法中分别调用了Solar_Sql_Model_Record::filter() 方法。当参数为空时,filter方法直接调用Solar_Sql_Model_Record::newFilter() 方法,获得当前的filter对象,进行验证并准备好invalid消息:

01. // apply filters
02.   $valid = $filter ->applyChain( $this );
03.  
04.   // retain invalids
05.   $invalid = $filter ->getChainInvalid();
06.  
07. // ...省略部分代码
08.   // was it valid?
09.   if (! $valid ) {
10.       // use custom validation messages per column when available
11.       foreach ( $invalid as $key => $old ) {
12.           $locale_key = "INVALID_" . strtoupper ( $key );
13.           $new = $this ->_model->locale( $locale_key );
14.           if ( $new != $locale_key ) {
15.               $invalid [ $key ] = $new ;
16.           }
17.       }
18.  
19.       $this ->_invalid = $invalid ;
20.       throw $this ->_exception( 'ERR_INVALID' , $this ->_invalid);
21.   }

那么Solar这样就能找到我们自定义的Filter么?还是不行,还要继续看Solar_Sql_Model_Record::newFilter() 方法, newFilter()方法的主要工作是实例化当前的Filter对象,

1. // create a filter object based on the model's filter class
2. $filter = Solar::factory( $this ->_model->filter_class);

大家肯定想了解下$this->_model->filter_class的内容吧?:) 还要麻烦大家查看一下Solar_Sql_Model::_fixFilterClass() 方法。这个方法设置了当前的Filter类。

1. $this ->_filter_class = $stack ->load( 'Filter' );

接着,Solar_Sql_Model_Record::newFilter() 把filter规则加入Filter对象,最后把本地字符串的对象设置为当前过滤器。filter规则来自几个方面:
1. 在模型文件中定义的, i.e., $this->_addFilter()
2. 手动使用$this->addFilter定义的
3. 表中定义为非空的及自动增长的字段

01. // set filters as specified by the model
02.   foreach ( $this ->_model->filters as $key => $list ) {
03.       // skip table cols that are not part of the fetch cols
04.       if (in_array( $key , $skip )) {
05.           continue ;
06.       }
07.       $filter ->addChainFilters( $key , $list );
08.   }
09.  
10.   // set filters added to this record
11.   foreach ( $this ->_filters as $key => $list ) {
12.       $filter ->addChainFilters( $key , $list );
13.   }
14.  
15.   // set which elements are required by the table itself
16.   foreach ( $this ->_model->table_cols as $key => $info ) {
17.       if ( $info [ 'autoinc' ]) {
18.           // autoinc are not required
19.           $flag = false;
20.       } elseif (in_array( $key , $this ->_model->sequence_cols)) {
21.           // auto-sequence are not required
22.           $flag = false;
23.       } else {
24.           // go with the col info
25.           $flag = $info [ 'require' ];
26.       }
27.  
28.       // set the requirement flag
29.       $filter ->setChainRequire( $key , $flag );
30.   }
31.  
32.   // tell the filter to use the model for locale strings
33.   $filter ->setChainLocaleObject( $this ->_model);

这一部分算是讲完了,但是如果仅仅是这样处理的话当我们使用Solar_Form创建表单并加入filter规则的时候,系统会提示找不到 filter规则,因为Solar仅在Solar_Filter_名字空间下查找我们自定义的Filter对象,而我们自定义的Filter对象在 Admin_Filter_名字空间下,也就是说系统根本没有实例化Admin_Filter类。在上面的解决方案 中,Solar_Sql_Model_Record实例化了Admin_Filter,并使用Admin_Filter进行filter操作,因为这里没 有用到模型,所以我们只能手动操作。

首先,在config.php文件中加入Solar_Filter的配置项,把Admin_Filter_名字空间加入Solar_Filter::_stack中:

1. $config [ 'Solar_Filter' ] = array (
2.      'classes' => array ( 'Admin_Filter' ),
3. );

这样的话系统就能找到我们自定义的filter了,不过local string仍然不行,我们还需要手动设置当前的filter local object,有两种方法:
1. 通过Solar_Fomr::setFilterLocaleObject 方法手动设置filter local object

1. $filter = Solar::factory( "Admin_Filter" );
2. $this ->form->setFilterLocaleObject( $filter );


2. 在实例化Solar_Form时指定local filter object

1. $this ->form = Solar::factory( "Solar_Form" ,
2.      array ( 'filter' => Solar::factory( 'Admin_Filter' )));

可以看到不管用哪种方法都需要手动实例化Admin_Filter类。

下一篇讲讲Solar_Form、Solar_Sql_Model_Record和Solar_Filter三者交织在一起的复杂关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值