Go to comments

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



Leave a comment 0 Comments.

Leave a Reply

换一张