PHP 超级全局变量
有9大超级全局变量(全部大写)
$_SERVER 服务器变量
$_ENV 环境变量
$_GET HTTP GET变量,接收url数据(常用)
$_POST HTTP POST变量,接收表单数据
$_REQUEST request变量
$_FILES HTTP文件上传时候用
$_COOKIE HTTP Cookies,接收客户端cookie的数据
$_SESSION Session变量,接收客户端session的数据
$GLOBALS Global变量,严格的说$GLOBALS不能叫全局变量,它只是所有变量的一个注册表
超级全局变量是系统已经声明好的,而且是以数组的形式存在的,
声明的普通全局变量,在函数内访问不到
$arr = array("棒棒鸡"); function demo(){ // global $arr; echo $arr[0]; // Notice: Undefined variable: arr i } demo();
常量在函数内能访问到,因为常量具有极强的穿透性,在哪都能访问,
超级全局变量,在任意的一地方,无论是多深层的函数内,还是面向对象的方法体内,都可以直接访问到
虽然是系统声明好的,但是我们可以放里面放值
$_GET = array("棒棒鸡"); function demo(){ echo $_GET[0]; // 棒棒鸡 } demo();
$_SERVER 获取web服务器的信息
foreach($_SERVER as $key => $value){ echo "{$key} => {$value}<br/>"; }
查看有多个元素
echo count($_SERVER); // 47
获取用户浏览器
echo $_SERVER['HTTP_USER_AGENT']; // Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36
获取HTTP主机
echo $_SERVER['HTTP_HOST']; // localhost
环境变量
echo $_SERVER['PATH']; // C:\Windows\SYSTEM32; // C:\Windows; // C:\Windows\SYSTEM32\WBEM; // C:\Windows\SYSTEM32\WINDOWSPOWERSHELL\V1.0\; // C:\Windows\SYSTEM32\OPENSSH\; // C:\PROGRAM FILES\GIT\CMD;C:\PROGRAM FILES\NODEJS\; // ; // C:\PROGRAM FILES (X86)\AMD\ATI.ACE\CORE-STATIC; // C:\Users\xxx\AppData\Local\Microsoft\WindowsApps; // C:\Users\xxx\AppData\Local\Programs\Microsoft VS Code\bin; // C:\Users\xxx\AppData\Roaming\npm; // D:\xampp\mysql\bin;
服务器软件,一般打印服务器环境的时候会用到
echo $_SERVER['SERVER_SOFTWARE']; // Apache/2.4.48 (Win64) OpenSSL/1.1.1k PHP/7.4.20
服务器的名称,服务器的IP,服务器的端口
echo $_SERVER['SERVER_NAME']; // localhost echo $_SERVER['SERVER_ADDR']; // 127.0.0.1 echo $_SERVER['SERVER_PORT']; // 80
客户端的IP
echo $_SERVER['REMOTE_ADDR'];
服务器发布网站的文档根目录
echo $_SERVER['DOCUMENT_ROOT']; // D:/xampp/htdocs
服务器使用的协议
echo $_SERVER['SERVER_PROTOCOL']; // HTTP/1.1
客户端请求的url
echo $_SERVER['REQUEST_URI']; // /index.php?user=admin
客户端请求的url不代参数
echo $_SERVER['SCRIPT_NAME']; // /index.php
还有一些是根据根据客户不同的请求出现的
比如,url加上 /user/add,访问 http://localhost/index.php/user/add $_SERVER数组变成50
echo count($_SERVER); // 50
多了PATH有关的信息,访问 http://localhost/index.php/user/add
echo $_SERVER['PATH_INFO'],'<br/>'; // /user/add echo $_SERVER['PATH_TRANSLATED'],'<br/>'; // D:\xampp\htdocs\user\add
所以预定义变量里面的值不是固定的,有时候会根据用户不同的请求,会增加或减少
获取客户端IP(重点提示)
通过 $_SERVER['REMOTE_ADDR'] 可能获取到80%的客户IP,
也有可能是获取不到的,因为客户端有时候是手机,或者是命令行直接请求网页,不同的请求就有不同获取IP的方式
在$_SERVER下面,
1. 如果有$_SERVER['HTTP_CLIENT_IP']就用这个
2. 上面的不存在,就用这个获取$_SERVER['HTTP_X_FORWARDED_FOR']
3. 这两个都不存在才用REMOTE_ADDR获取ip
4. 如果这三个都不存在,就获取不到IP了
function getIP(){ if(!empty($_SERVER['HTTP_CLIENT_IP'])){ // 如果不为空用HTTP_CLIENT_IP获取IP return $_SERVER['HTTP_CLIENT_IP']; }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ return $_SERVER['HTTP_X_FORWARDED_FOR']; }else if(!empty($_SERVER['REMOTE_ADDR'])){ return $_SERVER['REMOTE_ADDR']; }else{ return '未知IP'; } } echo 'IP:',getIP();
忘记从那里转的了
function getIP(){ global $ip; if (getenv("HTTP_CLIENT_IP")) $ip = getenv("HTTP_CLIENT_IP"); else if(getenv("HTTP_X_FORWARDED_FOR")) $ip = getenv("HTTP_X_FORWARDED_FOR"); else if(getenv("REMOTE_ADDR")) $ip = getenv("REMOTE_ADDR"); else $ip = "Unknow"; return $ip; } echo getIP();
服务器变量 $_SERVER
$_SERVER是一个包含头部信息(header)、路径(path)和脚本位置(script locations)的数组,
数组的实体由web服务器创建,不能保障所有的服务器都能产生所有的信息,服务器可能忽略了一些信息,或者产生了一些新的信息,
这是一个自动全局变量,在所有的脚本中都有效,在函数或方法中不需要使用global $_SERVER
环境变量 $_ENV
获取服务器和环境有关的东西,
在解析运行时,这些变量从环境变量转变为PHP全局变量名称空间(namespace),它们中的许多都是由PHP所运行的系统决定,
完整的列表是不可能的,请查看系统的文档以确定其特定的环境变量
这是一个自动全局变量,在所有的脚本中都有效,在函数或方法中不需要使用 global $_ENV
PHP里接收客户端的数据就下面三种,其它没法接收客户端数据
$_GET 接受用户通过url地址栏上传的参数
$_POST 接收用户通过HTTP协议向服务器传的参数,也称为http post传递
$_REQUEST 既有$_POST又有$_GET
这样写会报提示Notice: Undefined index: id in…,Notice不是报错是注意,Undefined index未定义的索引
$id = $_GET['id']; echo $id;
地址栏长度有限,根据不同浏览器数据4096字节,或者8192字节(一般是8192)
/** * $_GET接受地址栏上的参数 * php?id=9 * */ if(isset($_GET['id'])){ $id = $_GET['id']; echo $id; }
$_POST 随着HTTP协议传到服务器,php.ini文件搜索 post_max_size = 8M 通过修改改变post传输的大小
一个表单可以采用get和post一起提交
<?php function t(){ echo '姓名:',$_POST['username'],'<br/>'; echo 'Email:',$_POST['email'],'<br/>'; echo '性别:',$_POST['gender'],'<br/>'; echo '取出', $_GET['id'] ,'号帖子的内容'; } function t2(){ return t(); // 超全局变量,即使在函数内,甚至深层调用的函数内,也一样能接收到 } if($_POST){ $res = t2(); } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>post请求</title> </head> <body> <form action="index.php?id=99" method="post"> <h2>用户注册</h2> <p>用户名:<input type="text" name="username"></p> <p>Email:<input type="text" name="email"></p> <p> 男:<input type="radio" name="gender" value="男"> 女:<input type="radio" name="gender" checked="checked" value="女"> </p> <p><input type="submit" value="提交"></p> </form> </body> </html>
request是请求的意思,客户端传过来的get、post包括cookie都能接收,只要是客户端传给服务器端的信息,$_REQUEST都可以接收到
<?php if($_POST){ print_r($_GET); // Array ( [id] => 99 ) print_r($_POST); // Array ( [username] => 左琳 [email] => 770747402@qq.com [gender] => 女 ) print_r($_REQUEST); // Array ( [id] => 99 [username] => 左琳 [email] => 770747402@qq.com [gender] => 女 ) } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>post请求</title> </head> <body> <form action="index.php?id=99" method="post"> <h2>用户注册</h2> <p>用户名:<input type="text" name="username"></p> <p>Email:<input type="text" name="email"></p> <p> 男:<input type="radio" name="gender" value="男"> 女:<input type="radio" name="gender" checked="checked" value="女"> </p> <p><input type="submit" value="提交"></p> </form> </body> </html>
但是不建议用$_REQUEST,
因为get和post提交有重名的数据,会发生覆盖
如果不知道客户端是用post还是get请求
1. 可以声明一个数组
2. 然后判断一下
$arr = !empty($_POST)? $_POST : $_GET;
老版本里可以用$_GET或$_POST作为函数参数,新版的PHP里别用全局变量做函数的行参,会报错
function demo($_GET, $_POST){ }
get和post也可以以数组的方式传值
<a href="index.php?action[]=add&action[]=mod&id=6&name=admin">get请求</a>
post
<?php if($_POST){ print_r($_POST); // Array ( [username] => Array ( [0] => name1 [1] => name2 [2] => name3 ) ) } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>post请求</title> </head> <body> <form action="index.php" method="post"> <h2>用户注册</h2> <p>用户名:<input type="text" name="username[]"></p> <p>用户名:<input type="text" name="username[]"></p> <p>用户名:<input type="text" name="username[]"></p> <p><input type="submit" value="提交"></p> </form> </body> </html>
$_FILES
所有上传文件的信息都在$_FILES里,比如上传的文件名,上传的文件位置
$_COOKIE
setcookie('name', '努力', time()+3600, '/'); print_r($_COOKIE); // Array ( [name] => 努力 )
$_SESSION
1. 必须开启 session_start()
2. 赋值
3. 打印session数组
session_start(); $_SESSION['name'] = 'hello world'; print_r($_SESSION); // Array ( [name] => hello world )
$GLOBALS
打印$GLOBALS所有的变量和刚才的cookie全在globals里面
$a = 3; $b = 'hello'; print_r($GLOBALS); // Array // ( // [_GET] => Array // ( // ) // [_POST] => Array // ( // ) // [_COOKIE] => Array // ( // [name] => 努力 // [PHPSESSID] => 8ckftonuo30erm0v890be9jruj // ) // [_FILES] => Array // ( // ) // [GLOBALS] => Array // *RECURSION* // [a] => 3 // [b] => hello // )
在PHP4到PHP5.2这些全局变量还有一个别名
$_SERVER HTTP_SERVER_VARS
$_ENV HTTP_ENV_VARS
$_GET HTTP_GET_VARS
在PHP4的时候只能用这个 HTTP_SERVER_VARS 变量,后来PHP5.2改成$_SERVER
$GLOBALS包含所有的超级全局变量,它经常使用,
可以把数据变量放到$GLOBALS里,可以在任何的函数都可以使用,因为是全局的
php.ini文件
找到 register_globals = Off 修改 register_globals = On,
现在不能开启,被新版本禁止了
如果一旦开启,所有超全局数组里面的元素,可以当变量用,比如直接输出
$_GET['name'] = 'abc'; $_POST['age'] = 10; echo $name; echo $age;
$_REQUEST是$_GET, $_POST, $_COOKIE三者的并集
$GLOBALS是页面内所有全局变量的名单,在$GLOBALS里能找的我们声明过的所有变量
而$GLOBALS又是超全局的名单,这意味着我们通过$GLOBALS可以操作普通的变量
看一道面试题
写出如下程序输出的结果
$GLOBALS['var1'] = 5; $var2 = 1; function get_values(){ global $var2; $var1 = 0; // 这个$var1是局部变量,上面的$GLOBALS['var1']改的是全局变量,所以是两个是互补影响的两个变量 return $var2++; } get_values(); echo $var1,"\t\n"; // 5 echo $var2; // 2 // print_r($GLOBALS); /* Array ( [_GET] => Array ( ) [_POST] => Array ( ) [_COOKIE] => Array ( ) [_FILES] => Array ( ) [GLOBALS] => Array *RECURSION* [var2] => 2 [var1] => 5 ) */
因为面试题里有global关键字没讲过,所以燕十八老师简化了一下面试题
$var1 = 5; // 1. var1、var2 是普通的全局变量,在全局变量GLOBALS里注册 $var2 = 1; // 同上 function get_value(){ $var1 = 0; // 2. get_value函数有自己的空间,因此var1是局部变量 return $GLOBALS['var2']++; // 3. 但是$GLOBALS是全局的,因此GLOBALS['var2']直接影响的是全局的var2,加加变成2 } get_value(); echo $var1,'<br/>'; // 5 echo $var2; // 2
global关键字
$age = 5; function t(){ global $age; // global关键字,用在变量名前, // 声明,这个变量用的是"全局范围"内的$age,而不要在局部内生成$age $age++; } t(); echo $age; // 6
总结,函数内的局部变量和全局变量,并不是互相不能影响
1). 通过引用传参,能影响全局变量
2). 通过global关键字声明,也能直接使用外部的变量(不推荐,好多公司明确禁止使用global关键字)
3). 直接操作超级全局变量
服务器变量 $_SERVER
$_SERVER是一个包含头部信息(header)、路径(path)和脚本位置(script locations)的数组,
数组的实体由web服务器创建,不能保障所有的服务器都能产生所有的信息,服务器可能忽略了一些信息,或者产生了一些新的信息,
这是一个自动全局变量,在所有的脚本中都有效,在函数或方法中不需要使用global $_SERVER
环境变量 $_ENV
获取服务器和环境有关的东西,
在解析运行时,这些变量从环境变量转变为PHP全局变量名称空间(namespace),它们中的许多都是由PHP所运行的系统决定,
完整的列表是不可能的,请查看系统的文档以确定其特定的环境变量
这是一个自动全局变量,在所有的脚本中都有效,在函数或方法中不需要使用global $_ENV