Solar_Form与Solar_Filter相约鹊桥
其实这个主题之前@life的一篇文章中提到过,我在这里稍微补充一下。
Solar的模型非常强大,比Zend的不知强多少。但模型不是万能的,有时候为了使数据库更优雅,不得不放弃使用模型。就和Ajax不是万能的一样,当用户禁用JS时必须有后备方案。
前面我们讨论过也说Solar自定义Filter和Solar\_Form、Solar\_Sql\_Model\_Record和Solar\_Filter三者交织在一起的复杂关系了,今天我们就来讨论下Solar\_Form和Solar\_Filter这个话题,也是这一系列主题的完结篇。
刚才我有说过有时候需要折中而放弃模型的使用,现在我就介绍一种应用场景,比如:全站的配置表,很多人会把它放文件中,写成数组的形式返回,也有人会做成YAML或XML,总之都是存文件,这没有什么不妥,不过我更喜欢存数据库。无论是使用文件还是数据库,数据结构是一致的,都是键-值对形式,而一般来说值都不只一个, 如:配置全站的支付信息
键为:pay 值为: 支付宝 - alipay 财付通 - tenpay 网银在线 - bankonline
所以一般来说这里的值会是XML字符串形式或是数组序列化后的形式。 下面看下数据库设计:
CREATE TABLE `systems` ( `id` int(11) NOT NULL auto_increment, `key` varchar(16) NOT NULL COMMENT '键', `value` text COMMENT '值', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='系统设置表 - 键、值'
相信很多人都会这么做,:) 我们继续上面这个例子,先建表单:
$this->form = Solar::factory("Solar_Form", array('filter' => Solar::factory('Admin_Filter'))); // add payment elements $this->form->setElements(array( 'system[alipay_id]' => array('type'=>'text', 'label'=>'支付宝ID',), 'system[alipay_key]' => array('type'=>'text', 'label'=>'支付宝密钥',), 'system[alipay_email]' => array('type'=>'text', 'label'=> '支付宝邮箱',), 'system[bank_online_id]' => array('type'=>'text', 'label'=>'网银在线ID'), 'system[bank_online_key]' => array('type' => 'text', 'label'=>'网解在线密钥'), 'system[tenpay_id]' => array('type' => 'text', 'label' => '财付通ID'), 'system[tenpay_key]' => array('type' => 'text', 'label' => '财付通密钥'), ));
然后添加Filters
//------------------------------------------- // add filters for form //------------------------------------------- $this->form->addFilter('system[alipay_id]', array('validateNotBlank')); $this->form->addFilter('system[alipay_key]', array('validateNotBlank')); $this->form->addFilters('system[alipay_email]', array('validateNotBlank', 'validateEmail', 'validateDiscount'));
当提交表单时,填充值并验证
//------------------------------------------- // process save //------------------------------------------- if($this->_isProcess('save')) { $this->form->populate(); if(!$this->form->validate()) { var_dump($this->form->getInvalids()); exit; $this->form->addInvalid('system[alipay_email]', '邮件格式不正确'); return ; } if($this->_systemSave('pay', $data, $item)) { // if save success, redirect to this uri $uri = '/'.$this->_controller.'/'.$this->_action; return $this->_redirectNoCache($uri); } }
这个工作也就完成了,呵呵,大家注意看$this->form->getInvalids()方法,这个方法是我加到Solar\_Form中的,为了更方便地获得invalid消息,看看它的代码:
public function getInvalids($element = null) { $valids = $this->_filter->getChainInvalid($element); if(null === $element) { $return = array(); foreach($valids as $_element => $_valid) { $return[$_element] = $_valid[0]; } return $return; } else return $valids[0]; }