Thinkphp框架感悟(二)
这次主要分析一下I方法
/**
* 获取输入参数 支持过滤和默认值
* 使用方法:
* <code>
* I('id',0); 获取id参数 自动判断get或者post
* I('post.name','','htmlspecialchars'); 获取$_POST['name']
* I('get.'); 获取$_GET
* </code>
* @param string $name 变量的名称 支持指定类型
* @param mixed $default 不存在的时候默认值
* @param mixed $filter 参数过滤方法
* @param mixed $datas 要获取的额外数据源
* @return mixed
*
*/
function I($name,$default='',$filter=null,$datas=null) {
static $_PUT = null;
/**
* 这个if存在的意义是:I方法有一种写法为I('变量类型.变量名/修饰符');,这种写法可以通过修饰符的不同,将得到的变量强制转换为各个不同的类型
* 于是就需要一个if来判断是否为带“/”的写法。
* strpos()可以查出参数里第一个/的位置,
*
* 如果查到了“/”,则用explode将$name字符串拆成两个字符串.
* explode()的作用是将$name转换为一维数组,以"/"为标记拆分,
* 如:$demo = "abcd/12345"; var_dump(explode('/',$demo,2));
* 得到的结果为 array (size=2)
* 0 => string 'abcd' (length=4)
* 1 => string '12345' (length=5)
*
* 再通过list函数,将“/”前的字符串赋值给$name,将"/"后面的字符串赋值给$type
*
* 结果:$name为“变量类型.变量名”
* $type为“修饰符”
*
* 如果参数传入时的格式不是I('变量类型.变量名/修饰符')这种,
* 则查看是否设置“配置参数'VAR_AUTO_STRING'”,该参数的作用是默认强制转换为字符串 $type = 's';
*/
if(strpos($name,'/')){
list($name,$type) = explode('/',$name,2);
}elseif(C('VAR_AUTO_STRING')){
$type = 's';
}
/**
*这个if的运行过程与上一个if一样,判断传入的参数$name(也可以是经过上面步骤处理过的$name)。
* 最后变量类型(param、get、post等)被赋值给了$method。变量名被赋值给了$name
*
* 如果写的格式为I('变量名'),即没写“.”和变量类型,
* 则默认变量类型为param
*/
if(strpos($name,'.')) {
list($method,$name) = explode('.',$name,2);
}else{
$method = 'param';
}
/**
* strtolower()函数的作用是将字符全部转化为小写
* 通过$method1的不同,对$input赋不同的传输类型(注:此处的&不是很明白, &的用法是让两个变量指向同一个内容,不知去掉&会怎么样)
*/
switch(strtolower($method)) {
case 'get' :
$input =& $_GET;
break;
case 'post' :
$input =& $_POST;
break;
case 'put' :
if(is_null($_PUT)){
parse_str(file_get_contents('php://input'), $_PUT);
}
$input = $_PUT;
break;
/**
* 此处的$_SERVER是获取系统变量的方法,
* $_SERVER['REQUEST_METHOD'] 是查看访问页面时的请求方法。例如:“GET”、“HEAD”,“POST”,“PUT”。
* 从而达到“自动判断请求类型”的目的
* (所以,无论html页面传过来数据用的传输方法是get还是post,都能用param来接收)
*/
case 'param' :
switch($_SERVER['REQUEST_METHOD']) {
case 'POST':
$input = $_POST;
break;
case 'PUT':
if(is_null($_PUT)){
parse_str(file_get_contents('php://input'), $_PUT);
}
$input = $_PUT;
break;
default:
$input = $_GET;
}
break;
/**
* 下面依旧是通过$method1的不同,对$input赋不同的“关键变量名”,用以获取各种系统变量。
*/
case 'path' :
$input = array();
if(!empty($_SERVER['PATH_INFO'])){
$depr = C('URL_PATHINFO_DEPR');
$input = explode($depr,trim($_SERVER['PATH_INFO'],$depr));
}
break;
case 'request' :
$input =& $_REQUEST;
break;
case 'session' :
$input =& $_SESSION;
break;
case 'cookie' :
$input =& $_COOKIE;
break;
case 'server' :
$input =& $_SERVER;
break;
case 'globals' :
$input =& $GLOBALS;
break;
case 'data' :
$input =& $datas;
break;
default:
return null;
}
/**
* 此时$name的内容为变量名,而$input为$_post之类的接收类型变量
*
* 如果变量名$name为空,则意味着无变量名传入,传入的只是一个接收类型变量
* 那么这个接收类型变量里其实是所有的用该类型传输过来的内容(如只有$_POST则是一个数组,里面是各种来自method="post" 的表单中的值)
* 所以不写变量名代表不是接收特定的键值名传过来的内容,而是接收所有通过“该方法”传过来的内容,并存进“传输类型变量”这个数组里
* 所以,如果变量名$name为空,我们将整个接收到的数组赋值给$data,
* 其中isset函数的作用是检测变量是否存在:若变量不存在返回false,若其存在但值为null也返回false,只有存在且值不为null时才返回true
* 这个$filter是I方法的第二个传入参数,为“参数过滤方法”(一般我都没传过这个参数),所以当我们传入“参数过滤方法”时,会按我们传入的方法过滤
*
* 如果传入的$name不为空
* 则通过isset函数判断传过来的所有数据(是个二维数组,存放在$input($_POST之类)里面)里是否有键值名为$name的键值对
* 如果有,则将数据复制给$data,之后依然判断下是否传入了“参数过滤方法”,如果传入则过滤。
*/
if(''==$name) { // 获取全部变量
$data = $input;
$filters = isset($filter)?$filter:C('DEFAULT_FILTER');
if($filters) {
if(is_string($filters)){
$filters = explode(',',$filters);
}
foreach($filters as $filter){
$data = array_map_recursive($filter,$data); // 参数过滤
}
}
}elseif(isset($input[$name])) { // 取值操作
$data = $input[$name];
$filters = isset($filter)?$filter:C('DEFAULT_FILTER');
if($filters) {
if(is_string($filters)){
if(0 === strpos($filters,'/')){
if(1 !== preg_match($filters,(string)$data)){
// 支持正则验证
return isset($default) ? $default : null;
}
}else{
$filters = explode(',',$filters);
}
}elseif(is_int($filters)){
$filters = array($filters);
}
if(is_array($filters)){
foreach($filters as $filter){
if(function_exists($filter)) {
$data = is_array($data) ? array_map_recursive($filter,$data) : $filter($data); // 参数过滤
}else{
$data = filter_var($data,is_int($filter) ? $filter : filter_id($filter));
if(false === $data) {
return isset($default) ? $default : null;
}
}
}
}
}
/**
* 所以现在$data里面其实装的是传输过来的具体内容。
* 之后再判断下是否有$type(修饰符,在前面有过详解),如果$type不为空,则依据$type,将$data转化成不同的类型
* 如果$type为空,则判定是否传入参数$default(当传输内容不存在时的默认值),如果有$default,则将其赋值给$data
*/
if(!empty($type)){
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 = (string)$data;
}
}
}else{ // 变量默认值
$data = isset($default)?$default:null;
}
/**
* &&这个运算符的意思是:如果前面为假,那么后面的语句就不执行了。
* array_walk_recursive()函数的意思是:对数组中的每个元素应用用户自定义的函数(即:将数组$data放入函数think_filter中运算)(关于这个函数目前的用法我还不是很明确)。
* 最后先判断$data是否为数组,
* 如果是数组,则运行array_walk_recursive函数(因为array_walk_recursive函数的第一个参数必须得是数组)
*/
is_array($data) && array_walk_recursive($data,'think_filter');
/**
* 最后将$data输出
*/
return $data;
}
Thinkphp框架感悟(二)的更多相关文章
- Thinkphp框架感悟(一)
一.assign() /** * 分析: * 此处是Controller类里面的assign方法,我们一般写的控制器所调用的assign方法就是调的这个. * 而这个方法就干了三件事:1.获取传过来的 ...
- 制作类似ThinkPHP框架中的PATHINFO模式功能(二)
距离上一次发布的<制作类似ThinkPHP框架中的PATHINFO模式功能>(文章地址:http://www.cnblogs.com/phpstudy2015-6/p/6242700.ht ...
- ThinkPHP框架整合phpqrcode生成二维码DEMO
ThinkPHP框架发展到今天功能已经变得是非常强大了,但是ThinkPHP框架中没有二维码相关的库,因此我们可以通过整合phpqrcode来完成生成二维码的功能.想使用phpqrcode首先就要把p ...
- ThinkPHP框架学习(二)
在上一节中,我主要讲到了如何获取ThinkPHP框架,以及虚拟目录和虚拟主机的配置.准备工作完成之后,就可以利用ThinkPHP去部署项目了. 先在工作目录(D:/zend/workspace)下新建 ...
- 攻城记:Thinkphp框架的项目规划总结和踩坑经验
一.项目模块规划 1.项目分为PC端.移动端.和PC管理端,分为对应目录为 /Application/Home,/Application/Mobile,/Application/Admin: 对应入口 ...
- 关于在BAE上部署ThinkPHP框架的问题
现在有点小兴奋,因为在在BAE上部署ThinkPHP框架的问题快折腾一天了,午觉都没睡,不过没白整总算有点结果.不扯淡了,直入正题吧. 之前熟悉ThinkPHP框架,想在BAE上用ThinkPHP做点 ...
- 使用Thinkphp框架开发移动端接口
本文给大家分享的是使用thinkphp框架开发移动端接口的2种方法,一种是开发API,另外一种是实现移动端访问自动切换移动主题模板,从而实现伪app访问,下面我们就来详细看下如何实现吧. 方案一:给 ...
- 浅析Thinkphp框架中运用phprpc扩展模式
浅析Thinkphp框架中应用phprpc扩展模式 这次的项目舍弃了原来使用Axis2做web服务端的 方案,改用phprpc实现,其一是服务端的thinkphp已集成有该模式接口,其二是phprpc ...
- ThinkPHP框架视图详细介绍 View 视图--模板(九)
原文:ThinkPHP框架视图详细介绍 View 视图--模板(九) 视图也是ThinkPHP使用的核心部分: 一.模板的使用 a.规则 模板文件夹下[TPL]/[分组文件夹/][模板主题文件夹/]和 ...
随机推荐
- loj 1379(最短路变形)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27087 思路:题目的意思是求S->T的所有路径中花费总和小于 ...
- 判断App是否在后台运行
在一些场景中,经常会需要判断App是否在后台运行,比如是否显示解锁界面,收到新消息是否显示Notification等.需求可能是多样化的,但所依仗的原理是相通的,今天Stay打算说说这些需求的最优解. ...
- loopback 03
使用微信开发前准备 微信公众开发者平台 注册开发者账号获取权限: 安装包: wechat, wechat-oauth 微信公众平台操作 登录之后,得到appID和appsecret 根据appID和a ...
- iOS 注意事项
1.记得在项目中设置项目文件命名的prefix,避免命名冲突. 2.在适当的位置对属性和方法进行注释,建议利用插件(如VVDocument)提供效率.在给企业看文档时,可以利用(如Doxygen)这种 ...
- HttpClient 使用
Api支持 HttpClient 是基于Task的异步方法组,支持取消.超时异步特性,其可以分类为以下: Restful: GetAsync,PostAsync,DeleteAsync,PutAsyn ...
- 向量时钟Vector Clock in Riak
Riak 是以 Erlang 编写的一个高度可扩展的分布式数据存储,Riak的实现是基于Amazon的Dynamo论文,Riak的设计目标之一就是高可用.Riak支持多节点构建的系统,每次读写请求不需 ...
- C#数组的声明方式
C#数组的五种声明方式 一.声明一个未经初始化的数组引用,以后可以把这引用初使化为一个数组实例 int[] intArray; intArray = new int[10]; 注:数组的引用必须以相同 ...
- AngularJS进阶学习
参考:http://***/class/54f3ba65e564e50cfccbad4b 1. AJAX:Asynchronous JavaScript and XML(异步的 JavaScript ...
- BZOJ 2626 & KDtree
题意: 二维平面n个点 每次给出一个点询问距离第k小的点. SOL: kdtree裸题,抄了一发别人的模板...二维割起来还是非常显然的.膜rzz的论文. 不多说了吧.... Code: /*==== ...
- BZOJ 1086 & 类树的分块
题意: “余”人国的国王想重新编制他的 国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个 不同的城市之间 ...