详解thinkphp的I函数源码及运转流程和用法

来源:互联网 发布:js缺省参数 编辑:程序博客网 时间:2024/06/18 11:48

上次写了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;}





原创粉丝点击