详解thinkphp的I函数源码及运转流程和用法
上次写了U函数,今天就把I函数的源码解读和流程图记录下来,作为分享,顺便会对使用稍微做一些解释。
一 、函数使用方法:
参数1:$name
这个传递的是要过滤的变量名,里面可以包含数据来源方式method和数据类型type 格式为 method.name/type 例如 post.pram/s
method的方式非常多,具体最好参看源码,这里不具体说了。
要注意这里规定过滤数据的type后,会使用对应的强制转换,例如type为int,则用(int)方式进行转换。如果规定的type在I函数内不存在,则默认强制转换成字符串
type对应 a为数组 b为布尔 d为整形数 f为浮点数
参数2:$default
这个传递的是默认值,如果过滤后的变量不存在,则返回该默认值
参数3:$filter 默认为null
这个传递的是过滤的多个函数或者filter_id以及正则表达式
一个或多个函数:字符串格式多个函数用,隔开,还可以用数组方式,多个函数会循环进行过滤,且过滤的数据可以是多维数组,因为可以递归过滤,另外因为多个函数是循环进行过滤,所以过滤的顺序也是按照循环的顺序进行,所以要注意多个过滤函数的顺序放置。
正则表达式: /表达式/ 正则表达式的过滤方式不能进行递归,所以过滤的数据不能是数组
filter_id形式:整型的int类型或者数组类型都可以,最后用filter_var根据filter_id对应的过滤方式进行过滤,该种方式也是不进行递归的,所以过滤的数据不能是数组
参数4:$datas 默认为null
这个传递参数用来补充method中的data方式,是传递获取额外数据源的数据给过滤变量的
二、I函数运行流程图
三、I函数源码解读:
/**
* 获取输入参数 支持过滤和默认值
* 使用方法:
* <code>
* I('id',0); 获取id参数 自动判断get或者post
* I('post.name','','htmlspecialchars'); 获取$_POST['name']
* I('get.'); 获取$_GET
* </code>
* @param string $name 变量的名称 支持指定类型和method
* 格式 get.cc/d get为method cc为变量名称 d为指定数据类型
* @param mixed $default 不存在的时候默认值
* @param mixed $filter 参数过滤方法 可以是函数名,也可以是int类型指定filter_var里的过滤id
* @param mixed $datas 要获取的额外数据源
* @return mixed
*/
function I($name,$default='',$filter=null,$datas=null) {
/*建立静态变量$_PUT赋值为null*/
static $_PUT = null;
/*检查变量名称$name里面是否存在/*/
if(strpos($name,'/')){ // 指定修饰符
/*如果存在且/不是首字符,则根据其/分割为两个单元的数组,并用list分别赋值给$name以及$type
$name是变量名称,$type是变量模式,有强制转化为字符串模式s*/
list($name,$type) = explode('/',$name,2);
/*检测配置VAR_AUTO_STRING(强制将变量转化为字符串,如果需要变量本身,则必须加变量修饰符$)是否开启*/
}elseif(C('VAR_AUTO_STRING')){ // 默认强制转换为字符串
/*如果开启了,则将$type赋值为s,也就是字符串模式 ???*/
$type = 's';
}
/*检测$name变量名中是否含有.*/
if(strpos($name,'.')) { // 指定参数来源
/*如果有且不在首字符,则根据.分割成两个单元的数组,并用list分别将其赋值给$method以及$name
$method为 $name为*/
list($method,$name) = explode('.',$name,2);
/*如果不存在.*/
}else{ // 默认为自动判断
/*则将param赋值给$method*/
$method = 'param';
}
/*将$method转变为小写,并进行相应的判断*/
switch(strtolower($method)) {
/*如果是get*/
case 'get' :
/*则引用$_GET并赋值给$input*/
$input =& $_GET;
break;
/*如果是post*/
case 'post' :
/*引用$_POST并赋值给$input*/
$input =& $_POST;
break;
/*如果是put*/
case 'put' :
/*检查$_PUT是否为null*/
if(is_null($_PUT)){
/*如果是则获取php://input的内容并赋值给$_PUT php://input无法读取enctype=multipart/form-data的数据,会为空*/
parse_str(file_get_contents('php://input'), $_PUT);
}
/*将$_PUT的值赋值给$input*/
$input = $_PUT;
break;
/*如果是param则自动判断是哪种类型*/
case 'param' :
/*检查$_SERVER的请求方式*/
switch($_SERVER['REQUEST_METHOD']) {
/*如果是POST类型*/
case 'POST':
$input = $_POST;
break;
/*如果是PUT类型*/
case 'PUT':
if(is_null($_PUT)){
parse_str(file_get_contents('php://input'), $_PUT);
}
$input = $_PUT;
break;
/*不是以上两种则为GET类型*/
default:
$input = $_GET;
}
break;
/*如果是path类型*/
case 'path' :
/*设定$input为空数组*/
$input = array();
/*检查$_SERVER的path_info值是否为空*/
if(!empty($_SERVER['PATH_INFO'])){
/*不为空,则将url分隔符的配置赋值给$depr*/
$depr = C('URL_PATHINFO_DEPR');
/*去除$_SERVER['PATH_INFO']两端的url分隔符$depr,然后再根据$depr分割成数组赋值给$ipnut*/
$input = explode($depr,trim($_SERVER['PATH_INFO'],$depr));
}
break;
/*如果是request类型*/
case 'request' :
/*引用$_REQUEST的值赋值给$input*/
$input =& $_REQUEST;
break;
/*如果是session类型*/
case 'session' :
/*引用$_SESSION的值赋值给$input*/
$input =& $_SESSION;
break;
/*如果是cookie类型*/
case 'cookie' :
/*引用$_COOKIE类型赋值给$input*/
$input =& $_COOKIE;
break;
/*如果是server类型*/
case 'server' :
/*引用$_SERVER赋值给$input*/
$input =& $_SERVER;
break;
/*如果是globals类型*/
case 'globals' :
/*引用$_GLOBALS赋值给$input*/
$input =& $GLOBALS;
break;
/*如果是data类型,则直接调用用户传入的数据源$datas*/
case 'data' :
/*引用$datas赋值给$input*/
$input =& $datas;
break;
/*如果不属于以上任何类型*/
default:
/*则返回null*/
return null;
}
/*检测$name是否为空,$name是要读取的变量名*/
if(''==$name) { // 获取全部变量
/*如果为空将上面的$input赋值给$data*/
$data = $input;
/*检测用户是否设置$filter参数过滤方法,有则返回给$filters,
没有则将默认的过滤配置DEFAULT_FILTER的值返回给$filters*/
$filters = isset($filter)?$filter:C('DEFAULT_FILTER');
/*检测$filters是否存在*/
if($filters) {
/*如果存在,检查$filters是否为字符串格式*/
if(is_string($filters)){
/*如果是字符串,则用,分割$filters成数组重新赋值给$filters*/
$filters = explode(',',$filters);
}
/*循环$filters,将循环的值赋值给$filter*/
foreach($filters as $filter){
/*循环的每个$filter作为函数处理$data后返回给$data*/
$data = array_map_recursive($filter,$data); // 参数过滤
}
}
/*检查$input[$name]是否设置了*/
}elseif(isset($input[$name])) { // 取值操作
/*如果设置了,则将$input[$name]赋值给$data*/
$data = $input[$name];
/*检查用户是否设置$filter,设置了则赋值给$filters,否则用默认的过滤配置赋值给$fitlers*/
$filters = isset($filter)?$filter:C('DEFAULT_FILTER');
/*检查$filters是否存在*/
if($filters) {
/*检查$filters是否为字符串*/
if(is_string($filters)){
/*如果是字符串,则检查$filters首字符是否为/*/
if(0 === strpos($filters,'/')){
/*如果首字符为/则认定为过滤方法是正则匹配的方式,所以将$data强制转换成字符串,
然后将$filters作为正则匹配的表达式,用preg_match进行匹配,并检测匹配结果*/
if(1 !== preg_match($filters,(string)$data)){
// 支持正则验证
/*如果不匹配,则返回用户提交的$default值,如果用户没有设定$default,则返回null*/
return isset($default) ? $default : null;
}
/*如果$filters首字符不是/*/
}else{
/*则根据,分割$filters并重新赋值给自身*/
$filters = explode(',',$filters);
}
/*如果$filters不为字符串,则检测是否为int类型*/
}elseif(is_int($filters)){
/*如果是int类型,则将$filters强制转变为数组并赋值给$filters*/
$filters = array($filters);
}
/*检查$filters是否为数组*/
if(is_array($filters)){
/*将$filters循环,每次循环的值赋值给$filter*/
foreach($filters as $filter){
/*检查循环出来的$filter函数是否存在*/
if(function_exists($filter)) {
/*如果存在,则检测$data是否是数组,如果是则用array_map_recursivve递归执行$filter函数处理$data
如果不是数组,则直接用$filter作为函数处理$data,最后将执行结果赋值给$data*/
$data = is_array($data) ? array_map_recursive($filter,$data) : $filter($data); // 参数过滤
/*如果$filter函数不存在*/
}else{
/*检查$filter是否是int类型,如果是,则返回$filter,如果不是,则用filter_id获取其对应的id返回
将返回值,作为filter_var的第二次参数过滤选型对$data进行过滤,处理完后返回赋值给$data*/
$data = filter_var($data,is_int($filter) ? $filter : filter_id($filter));
/*检查$data是否为false*/
if(false === $data) {
/*检查用户提交的$default是否设置,如果设置则返回$default,如果没有设置则返回null*/
return isset($default) ? $default : null;
}
}
}
}
}
/*如果$type不为空*/
if(!empty($type)){
/*根据转为小写后的$type类型来强制转换$data的类型*/
switch(strtolower($type)){
case 'a': // 数组
$data = (array)$data;
break;
case 'd': // 数字
$data = (int)$data;
break;
case 'f': // 浮点
$data = (float)$data;
break;
case 'b': // 布尔
$data = (boolean)$data;
break;
case 's': // 字符串
/*如果以上都不符合*/
default:
/*则将$data强制转换成字符串类型*/
$data = (string)$data;
}
}
/*如果$name不为空值,同时不存在$input[$name]*/
}else{ // 变量默认值
/*则检查用户提交的$default默认值是否设置,如果设置了返回其作为$data,如果没有设置,则返回null作为$data*/
$data = isset($default)?$default:null;
}
/*检查$data为数组的话,则使用array_walk_recursive处理$data递归使用执行think_filter函数,
think_filter猜测是对数据查询进行特别过滤,匹配查询语句的都在后方添加了一个空格,这里我自己
也没太懂*/
is_array($data) && array_walk_recursive($data,'think_filter');
/*返回$data*/
return $data;
}
下一篇: oracle定时任务,两张表同步状态