欢迎访问织梦学习网,加群!!!!!!!!!!!!!!!!
当前位置:主页 > 二次开发 >

织梦中预定义的超全局数组处理

2019-07-14 dedecms二次开发 织,梦中,预,定义,的,超,全局,数组,处理,当,
  当我们写好表单后,提交到对应php文件进行处理,在处理前首先要接收数据,然后对数据处理,以申请友情链接为例子。

  友情链接申请界面如下图所示:

  当我们提交flink.php后,正常情况是flink.php会用超全局数组$_POST来接收数据,但是打开flink.php文件,我们完全找不到$_POST,难道dedestudy.cn/' target='_blank'>织梦不用$_POST,dedestudy.cn/' target='_blank'>织梦也是用php开发的,所以,收集数据必定会用到$_POST,但是如果你仔细分析织梦源码的话,你会发现每个对表单提交过来的数据进行处理的文件,都找不到$_POST或$_GET等超全局数据。

  以前刚学习php时,看织梦系统源码,非常费事,就拿这样刚开始时让我纠结了好久,等看多了织梦系统源码,才知道,原来织梦把这些超全局变数组,都做了处理,这样以后我们无需每次处理表单,都要多写$_POST或$_GET等多余的代码了。

  我们看一下织梦里面的这个flink.php文件,找到下面几行:

    $msg = htmlspecialchars($msg);
    $email = htmlspecialchars($email);
    $webname = htmlspecialchars($webname);
    $url = htmlspecialchars($url);
    $logo = htmlspecialchars($logo);
    $typeid = intval($typeid);

  织梦直接用类似$msg来收集表单来的数据,正常应当是$msg = $_POST['msg'],现在变成了$msg = $msg(htmlspecialchars()这个函数的功能是把一些预定义的字符转换为 HTML 实体,这与超全局变量没有关系),是不省了不少事,也许大家会问,也省不了多少,这只是一个文件,而织梦时面的处理表单的文件,不止数十个,加起来就量就非常大了,这样不仅可以减少代码,而且,还省不少事。

  这个功能是如何实现的?织梦是在入口文件common.inc.php里面定义的,找到这个文件,代码如下:

    foreach(Array('_GET','_POST','_COOKIE') as $_request)
    {
        foreach($$_request as $_k => $_v)
        {
            if($_k == 'nvarname') ${$_k} = $_v;
            else ${$_k} = _RunMagicQuotes($_v);
        }
    }

  首先遍历声明的数组Array('_GET','_POST','_COOKIE'),再通过第二次循环遍历,就可以实现了上面的提到简略形式,其中$$_request正是类似的$_GET,$POST,$_COOKIE。$$_request是可变变量,在下面的教程里讲到。在这二又重循环中用到了一个函数_RunMagicQuotes(),还有一个函数CheckRequest()。

  不仅这个超全局变量了这种简略思想,在上传文件收集上传信息的$FILES也用了这种思想,作为一个技术员,可以好好研究一下织梦一些设计思想,一定会对我们大有用处。


扩展学习:

  要看明白织梦对预定义的超全局数组(预定义的超全局数组也叫预定义的超全局变量)是如何处理优化的,首先得明白这些超全局数组$_GET、$_POST、$_REQUEST、$GLOBAL、$COOKIE、$SESSION等是什么意思,它们是如何运作的?只有把这些基本的概念弄明白了,才能对织梦里面的超全局数组的应用有更好的把握。

  要知道预定义全局数组首先要知道什么是变量、什么是局部变量、什么是全局变量。

变量常识:

  当我们声明了一个变量,php就会给变量分配一个空间,这个空间包括变量名、变量的地址和存储变量值空间,例如,声明变量$age=10,在栈内存中示意图如下所示。

  当我们连续声明二个同样的变量即$a=5;$a=7;最后$a的值是7,前面的变量会被后面的变量覆盖掉。

  当我们使用地址引用即在变量前面加上&符号后,例如$a=5;$b=&$a;这时的变量$b里面的存储的是变量a的地址,如果改变$a的值那么,$b的值同样也改变,因为,$b指向$a,如下图所示。


  此时,如果unset($a)销毁变量$a,是不是变量$b也跟着销毁呢?不是的,变量$b仍然存在,且值不变。

  如果$a=5;$b=&$a;$c=10;$b=&$c,若现在我们把$c赋值为20即$c=20,请问echo $b的结果是多少?打印结果是20,也就是说$b现在的已经“抛弃”$a,转向指向$c了,$b具有“喜新厌旧”的特性。

  我们定义的变量都是由超全局变量$GLOBAL来管理的。

可变变量:

  什么是可变变量?看下面的例子:

  <?php

$a="good";
 
$$a="ok";

echo $good;
?>

  打印结果是:ok,在这里$$a就是$good,本来good是$a的值结果经过二个$$符号,把原来是作为值的good变成了另一个变量,这就是可变变量。还可以把$$a再加上一个$符号变成$$$a现在的$$$a与$ok等价,原来是值的ok现在也变成了变

量。可变变量在php程序开发中也是经常用到的,在织梦里面的入口文件common.inc.php里面下面代码里面,

foreach(Array('_GET','_POST','_COOKIE') as $_request)
    {
        foreach($$_request as $_k => $_v)
        {
            if($_k == 'nvarname') ${$_k} = $_v;
            else ${$_k} = _RunMagicQuotes($_v);
        }
    }

  这段代码就有用到可变变量。$$request其实就是$_GET 或$_POST或$_COOKIE,在织梦系统里面,用这些可变变量的地方还有文件上传功能里面等。


局部变量:

  在php里面的变量有局部变量,有全局变量,他们是相对而言的,举一个简单的例子,如果我们定义一个函数,在函数内部定义一个变量$a,那么,这个$a就是一个局部变量,他只能在这个函数中起作用,超出这个函数,这个变量就不起作用了,言外之意就是函数里面的变量不可以访问函数外的变量,举例子说明,例如有一个sum.php的程序文件,里面有如下代码。
 
  例子:

<?php

$a=5;

function sum($a){

$a+=7;

}
echo sum(3);
echo $a;

?>

  在这个例子中,函数sum()外面的变量$a和函数内部的$a虽然变量名完全一样,但是这他们是完全不同的二个变量,只是名字一样,就像重名的二个人,虽然,姓名一样,但是人完全不一样。这二个变量互不影响,相互独立。执行完这段代码后的结果是:10,5,结果正好说明这一点。

全局变量:

  在函数外部声明的变量,就是全局部量,全局变量可以在函数中使用,但前提是在要函数内部用global 全局变量名,声明后,就可以在函数中使用了。例如。

<?php
$a=5;

function say(){
  global $a;
  echo $a;
}
say();

?>

  如果在函数体外声明global $a,在函数内不能使用,例如:

<?php
global $a;
$a=5;

function say(){
  echo $a;
}
say();

?>

  这样是错误的!打印不出内容来。

  预定义超全局数组,我们知道,我们定义的变量都是有一定的作用域或称为作用范围的,但是在php系统里面系统定义了几个变量,这些变量在我们使用它们时,无需声明就可以使用,不管在什么地方,这些变量就是超全局变量,又称超全局数组,常用的超全局变量有9个,分别是$_GET、$_POST、$_SESSION、$_SERVER、$_COOKIE、$_REQUEST、$_ENV、$_FILES、$GLOBAL。

  这些超全局变量都有不同的作用,其中$_REQUEST包括$_GET,$_POST,$_SESSION这三个,也就是我们完全可以用$_REQUEST来代替这三个,但是请注意,这个会带来安全风险,所以,在一般情况下,当我们不知道传过来的值是用的什么方法时,我们才用$_REQUEST。但请请尽量不要用这个$_REQUEST。

  如果我们不知道传值方法的话,我们可以通过$_SERVER['REQUEST_METHOd']来判断访问页面使用的请求方法。

  我们分析一个超全局变量$_GET它是如何运行的。

  现在我们看一个例子:文件userlogin.php里面的代码是:
<?PHP
echo "你好"."<br>";

print_r($_GET);

?>
 
  当我们在浏览器输入http://www.dedebase.com/userlogin.php时,显示的结果是:

你好
Array ( )

  如果我们地址栏输入http://www.dedebase.com/userlogin.php?aa=bb&cc=nihao后,显示结果如下所示:


问题:

  当我们在userlogin.php后面加上 ?aa=bb&cc=nihao,程序自动帮我们收集问号后面的内容,并分装到数组里面,这是为什么呢?为什么一个$_GET就能得到一个数组,它是如何运行的呢?

  $_GET 运行原理:当我们在浏览器输入http://www.dedebase.com/userlogin.php?aa=bb&cc=nihao后,浏览器通过http协议访问apache(如果你空间装的是iis那么,他会访问iss)服务器,然后,apache服务器调用php模块,把提交的数据(也就是问号后面的aa=bb&cc=nihao)封装成超全局数组$_GET,并发给文件userlogin.php,然后,php模块把userlogin.php调用后的内容,发送给apache服务器,apache服务器,再把内容通过http协议发送给浏览器,浏览器就显示出如上图所示内容了。

  为了方便大家更直观的理解$_GET原理,制作如下图。

  现在又有一个问题,当我们通过get方法,即userlogin.php?aa=你好&cc=nihao传递中文参数时,在ie5,ie6下面会出现问题。如果是偶数个汉字,是正常显示的,如果是奇数位汉字,userlogin.php?aa=你好吗&cc=nihao这样传递参会出现乱码。

  解决方法:

  第一种:直接在userlogin.php?aa=你好吗&cc=nihao里面的“你好吗”后面加全角空格,即userlogin.php?aa=你好吗 &cc=nihao,然后在服务器端用trim()函数把空格去掉,这样就可以解决在ie5,ie6下的乱码,但这样不好。我们可以用第二种方法。

  第二种:用urlencode()进行编码,$str=urlencode("你好吗"),即userlogin.php?aa=".$str."&cc=nihao,后然,在服务器接收时用decode($_GET['aa'])解码(解码可以不用,php系统已经给我们自动帮我们解码)。