php ignore special characters,thinkphp模型自动完成中的ignore

ThinkPHP中的模型有一个自动完成的功能,非常好用。我们经常在对用户的密码进行加密的时候使用这个功能,比如一个用户注册的时候,我们写一个模型方法,直接完成注册,而在数据插入到数据库之前,自动对密码字段进行了加密。

Model User;

$_auto = array(

array(password,md5)

);

function register($username,$password)

上面的$username和$password都是用户提交的信息,而在数据库中,我们查看数据,发现密码字段已经自动加密了。但是,有一个情况比较复杂,就是在用户更新数据的时候。

function update($uid,$password,$data) {

$this->check_pass($uid,$password);

$this->create($data,self::MODEL_UPDATE);

$this->save();

}

我们一般的情况是:需要输入原始密码进行校验,校验通过后才能修改密码。但是也有一个情况是,用户并不希望修改密码,所以新密码字段留空,而修改了其他字段。这种情况下,ThinkPHP提供了一个ignore(忽略,不处理)的自动完成条件来处理。如下:

protected $_auto = array(

array('password', '', self::MODEL_UPDATE, 'ignore'),

// 解释一下,第一个元素是指字段名,第二个元素是指当该字段的值为什么的时候执行忽略操作(不一定为空,也可以是其他值)

);

当提交的密码为空的时候,就会执行ignore动作。但是ThinkPHP的官方文档中,并没有说明,当两个自动完成同时使用的时候,应该怎么处理,比如password既要执行md5又要执行ignore时应该怎么处理。所以,我们必须去把自动完成的源码翻出来进行剖析。

自动完成的源码在/ThinkPHP/Library/Think/Model.class.php文件中的autoOperation函数来实现:

/** * 自动表单处理

* @access public

* @param array $data 创建数据

* @param string $type 创建类型

* @return mixed

*/

private function autoOperation(&$data,$type) {

if(false === $this->options['auto']) { // 关闭自动完成

return $data;

}

if(!empty($this->options['auto'])) {

$_auto = $this->options['auto'];

unset($this->options['auto']);

}

elseif(!empty($this->_auto)) {

$_auto = $this->_auto;

}

// 自动填充

if(isset($_auto)) {

foreach ($_auto as $auto){

// 填充因子定义格式

// array('field','填充内容','填充条件','附加规则',[额外参数])

if(empty($auto[2])) $auto[2] = self::MODEL_INSERT; // 默认为新增的时候自动填充

if( $type == $auto[2] || $auto[2] == self::MODEL_BOTH) {

if(empty($auto[3])) $auto[3] = 'string';

switch(trim($auto[3])) {

case 'function': // 使用函数进行填充 字段的值作为参数

case 'callback': // 使用回调方法

$args = isset($auto[4]) ? (array)$auto[4] : array();

if(isset($data[$auto[0]])) {

array_unshift($args,$data[$auto[0]]);

}

if('function'==$auto[3]) {

$data[$auto[0]] = call_user_func_array($auto[1], $args);

}

else {

$data[$auto[0]] = call_user_func_array(array(&$this,$auto[1]), $args);

}

break;

case 'field': // 用其它字段的值进行填充

$data[$auto[0]] = $data[$auto[1]];

break;

case 'ignore': // 为空忽略if($auto[1]===$data[$auto[0]])unset($data[$auto[0]]);

break;

case 'string':

default: // 默认作为字符串填充

$data[$auto[0]] = $auto[1];

}

if(isset($data[$auto[0]]) && false === $data[$auto[0]] ) unset($data[$auto[0]]);

}

}

}

return $data;

}

上面是实现自动完成的源码,可以看到,核心代码用红色标注出来,当采用ignore作为动作行为选项时,判断array的第二个元素和传过来的数据(如$_POST)的对应字段是否有相同的值(全等,所以null !== '',要注意),如果全等,就直接unset这个字段,这样在更新的时候就不会更新这个字段。

如果我们有两条语句,如下:

protected $_auto = array(

array('password', '', self::MODEL_UPDATE, 'ignore'),

array('password', 'md5', self::MODEL_UPDATE, 'function')

);

那么,无论你如何改变这两个条件的顺序,都会导致密码被md5加密,只是顺序不同,加密的结果不同而已。那么这是由什么产生的呢?是由上面源码中的蓝色标识代码产生的。$_auto的每一个元素数组都会被执行,案例中的第二个自动完成不会自动消失,而是会执行:md5在前面执行,和在后面执行,都会产生结果。

那么怎么来达到我们的目的呢?其实很简单,我们反而是利用foreach这个本质规律,先执行一个我们自己写的加密函数,如果结果为空,那么再执行ignore即可。代码如下:

protected $_auto = array(

array('password', 'md5_password', self::MODEL_UPDATE, 'callback'),

array('password', '', self::MODEL_UPDATE, 'ignore')

);

protected function md5_password($password) {

if(!$password) return '';

return md5($password);

}

我们利用到了另外一个自动完成的规则,及callback。它实际上和function是一样的,只不过callback调用的是本模型类的一个方法而已,实际上,我们也可以自己在common中写一个函数来达到这个效果。

要注意自动完成的顺序,当第一个规则执行完之后,我们来看一下。如果你传过来的密码是空的,那么md5_password函数返回的值是'',而再去执行第二个自动完成规则ignore时,password字段就被忽略了。这样就达到了我们要的目的。

有两个注意点:1.自动完成规则的顺序必须是先执行md5_password函数,然后在执行ignore;2.md5_password在忽略条件下必须返回和ignore要忽略的值相同的值。

2015-11-24

3411

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值