2.4、PHP数组与数组结构

根据数组的下标( integer 和 string )不同,分为索引数组和关联数组。但是官方说法是PHP 数组可以同时含有 integer 和 string 类型的键名,因为 PHP 实际并不区分索引数组和关联数组。

一、定义数组
数组结构:
键(key)可以是整数 integer 或字符串 string
值(value)可以是任意类型的值

array(  key =>  value
     , ...
     )

eg:


$array = array(
    "foo" => "bar",
    "bar" => "foo",
);

// 自 PHP 5.4 起
$array = [
    "foo" => "bar",
    "bar" => "foo",
];

注意事项:
key 会有如下的强制转换:
1、包含有合法整型值的字符串会被转换为整型。例如键名 “8” 实际会被储存为 8。但是 “08” 则不会强制转换,因为其不是一个合法的十进制数值。
2、浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
3、布尔值也会被转换成整型。即键名 true 实际会被储存为 1 而键名 false 会被储存为 0。
4、Null 会被转换为空字符串,即键名 null 实际会被储存为 “”。
5、数组和对象不能被用为键名。坚持这么做会导致警告:Illegal offset type。
6、如果在数组定义中多个单元都使用了同一个键名,则只使用了最后一个,之前的都被覆盖了。
7、key 为可选项。如果未指定,PHP 将自动使用之前用过的最大 integer 键名加上 1 作为新的键名。

eg:


$array = array(
         "a",
 "08" => "b",
  072 => "c",
         "d",
  9.7 => "e",
  true =>"f",
  NULL =>"g",
		 "f",
);
var_dump($array);
/*输出array (size=8)
  0 => string 'a' (length=1)
  '08' => string 'b' (length=1)
  58 => string 'c' (length=1)
  59 => string 'd' (length=1)
  9 => string 'e' (length=1)
  1 => string 'f' (length=1)
  '' => string 'g' (length=1)
  60 => string 'f' (length=1)*/
	
/**
 * 在给数组赋值时,给出方括号但没有指定键名,则取当前最大整数索引值,新的键名将是该值加上 1(但是最小为 0)。
 * 如果当前还没有整数索引,则键名将为 0。注意这里所使用的最大整数键名不一定当前就在数组中。
 * 它只要在上次数组重新生成索引后曾经存在过就行了。有点类似于数据库中的主键
 */
// 创建一个简单的数组
$array = array(1, 2, 3, 4, 5);
print_r($array);

// 现在删除其中的所有元素,但保持数组本身不变:
foreach ($array as $i => $value) {
    unset($array[$i]);
}
print_r($array);

// 添加一个单元(注意新的键名是 5,而不是你可能以为的 0)
$array[] = 6;
print_r($array);

// 重新索引:
$array = array_values($array);
$array[] = 7;
print_r($array);
/*输出
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
)
Array
(
)
Array
(
    [5] => 6
)
Array
(
    [0] => 6
    [1] => 7
)*/

二、数组遍历
1、由于for局限性,遍历数组很少使用for,一般使用foreach,这里主要介绍下foreach遍历。
语法:

foreach ($array as $value){
	...
}
    
foreach ($array as $key => $value){
	...
}

可以通过在 $value 之前加上 & 来修改数组的元素。此方法将以引用赋值而不是拷贝一个值。数组最后一个元素的 $value 引用在 foreach 循环之后仍会保留。建议使用 unset() 来将其销毁。
eg:


$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // 最后取消掉引用

$value 的引用仅在被遍历的数组可以被引用时才可用(例如是个变量)。以下代码则无法运行:
eg:


foreach (array(1, 2, 3, 4) as &$value) {
    $value = $value * 2;
}

2、list,each,while联合使用遍历数组
先声明的是,这种方法很少使用。且由于本身限制很多,搞的我都不想写这一块。
1)list
像 array() 一样,这不是真正的函数,而是语言结构。 list() 可以在单次操作内就为一组变量赋值。
注意:
①list() 仅能用于数字索引的数组,并假定数字索引从 0 开始,而且必须是索引数组(键名从0开始,且连续),数组中可以含非数字的键名,描述的可能有点矛盾,下边示例中,一目了然。
②PHP 5 里,list() 从最右边的参数开始赋值; PHP 7 里,list() 从最左边的参数开始赋值。官方说后期还可能会变化。
③在 list() 执行过程中修改数组(比如使用 list($a, $b) = $b)将会产生不可预知的结果。


$info = array('a', 'b', 'c');

// 列出所有变量
list($a, $b, $c) = $info;
var_dump($a,$b,$c);//输出'a','b','c'

// 列出他们的其中一个
list($a, , $b) = $info;
var_dump($a,$b);

// 或者让我们跳到仅第三个
list( , , $a) = $info;
var_dump($a);

// list() 不能对字符串起作用
list($bar) = "abcde";
var_dump($bar); // NULL

//php5,php7区别
list($d[], $d[], $d[]) = [1, 2, 3];
var_dump($d);//php5输出array(3,2,1),php7输出array(1,2,3)

//输出顺序,这也是对list,each,while联合使用的关键
list($e,$f,$g) = array(0=>'b',2=>'a',1=>'c','a'=>'d');
var_dump($e,$f,$g);//注意输出顺序,输出bca

//使用嵌套的 list()
list($a1, list($b1, $c1)) = array(1, array(2, 3));
var_dump($a1, $b1, $c1);

2、each
返回 array 数组中当前指针位置的键/值对并向前移动数组指针。键值对被返回为四个单元的数组,键名为0,1,key和 value。单元 0 和 key 包含有数组单元的键名,1 和 value 包含有数据。
如果内部指针越过了数组的末端,则 each() 返回 FALSE。

eg:


$foo = array("a", "b", "c");
$bar = each($foo);
$bar1 = each($foo);
var_dump($bar,$bar1);

/*输出
array (size=4)
  1 => string 'a' (length=1)
  'value' => string 'a' (length=1)
  0 => int 0
  'key' => int 0
array (size=4)
  1 => string 'b' (length=1)
  'value' => string 'b' (length=1)
  0 => int 1
  'key' => int 1
*/

list,each,while联合遍历数组
eg:


$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

reset($fruit);
while (list($key, $val) = each($fruit)) {
    echo "$key => $val\n";
}

三、控制数组内部指针来控制函数遍历数组
current() - 获取目前指针所指向资料的键值
end() - 将数组的内部指针指向最后一个单元
key() - 获取目前指针所指向资料的索引值
each() - 返回数组中当前的键/值对并将数组指针向前移动一步
prev() - 将数组的内部指针倒回一位
reset() - 将数组的内部指针指向第一个单元
next() - 将数组中的内部指针向前移动一位
以上函数参数都只有一个,就是数组本身

目前并未发现这个内部指针变动对foreach循环数组有什么影响,影响的可能只是each这些函数遍历数组。但是由于each使用较少,这些函数用处似乎并不是很大。

四、预定义数组–超全局变量
超全局变量是在全部作用域中始终可用的php内置变量。

1、$_SERVER 
服务器和执行环境信息
2、$_GET、$_POST、$_REQUEST
①$_GET,通过 URL 参数传递给当前脚本的变量的数组,假设用户访问的是http://example.com/?name=Hannes那么
echo 'Hello ' . htmlspecialchars($_GET["name"]) . '!';将会输出Hello Hannes!
②$_POST,获取form表单post提交或者ajax的post提交等数据。
③$_REQUEST,默认情况下包含了 $_GET,$_POST 和 $_COOKIE 的数组。
区别:
①get和post提交数据的方式不同
②GET方式提交数据安全性非常低,POST安全性较高,REQUEST获取数据较慢。
③get传送的数据量较小,这取决于URL长度,url长度http协议上没有限制,但是一般浏览器对其有限制,不同浏览器限制长度不同,另外服务器的操作系统也会有限制,如果url太长,服务器可能会因为安全方面的设置从而拒绝请求或者发生不完整的数据请求。post大小设置在php.ini中可以设置,post上传最大限制和文件最大上传大小限制post_max_size和upload_max_filesize
$_FILES
3、$_COOKIE、$_SESSION
以下是初学php时对cookie、session的总结,由于cookie和session涉及知识点太多,暂时只做如下总结:
session:其数据保存在服务器端。
注意事项:在使用session之前要将session开启,并且一页面有且只有一个session_start()。在session_start()之前不能有任何输出,在顶部,与php标签不能有空格。可以重新赋值。一般php框架都做了这一步。
①session的写入:
session_start();一般php框架对session使用做了封装
在session_start写入之前不能有任何输出,一般放在页面最顶部。
$_SESSION['']添加其数组的元素。
②session的清空                                                                     
session_destroy();(清空所有已注册session)
unset ($_SESSION[''])='';(清空指定的session)
③session的保存时间
   在php.ini中有一个配置项session.gc_maxlifetime设置的失效时间是指,保存session的文件“最后修改时间”到”现在”超过了gc_maxlifetime设置值,那么此时session失效。简单的说,如果我登录到某网站,如果在1440秒(默认值)内没有操作过,那么对应的session就认为是过期了。
   当然session保存时间没有这么简单,session回收机制,程序中对其时间作出修改,或者对其session文件做定时更新什么的。
④session保存地址
   在php.ini里的配置session.save_path默认是注释掉的,Seesion保存的路径
	Linux:/tmp 或 /var/lib/php/session
	Windows:C:\WINDOWS\Temp
cookie
①写入
不能用数组的形式定义:$_COOKIE['username']='sky';
setcookie('cookie名','值','保存时间(时间戳)');
时间戳:time():自1970年1月1日0时0分0秒到现在的秒数
setcookie('username','sky','time()+60*60*24');
②读取
print_r($_COOKIE);//一般php框架对cookie的使用做了封装
③销毁
(1)setcookie('username','',0)将cookie过期时间设置为0
(2)不能用unset($_COOKIE['username'])销毁;
④特点
(1)cookie有时间限制,一般较长
(2)cookie保存在客户端,保存在每一个浏览器的下面
(3)只要未过有效时间或未被清除,是可以继续使用的。安全性较低

4、$_ENV
包含服务器端环境变量的数组,默认情况下,$_ENV为空,因为在php.ini中variables_order = "GPCS",前面少了个E
EGPCS是Environment、Get、Post、Cookies、Server的缩写,如果variables_order 的配置中缺少E ,则PHP 无法
接受环境变量,那么$_ENV 也就为空了。
由于开启$_ENV,即variables_order = "EGPCS"会导致一些性能损失,不推荐使用。更推荐使用getenv (string $varname)
函数来获取Environment中的值,getenv的参数就是$_ENV中的键名,可以通过phpinfo();来查看,搜索Apache Environment
就可看到。

5、$GLOBALS
一个包含了全部变量的全局组合数组。变量的名字就是数组的键。

浏览器禁用cookie,能否使用session
当php.ini中的session.use_cookie=1(sessionid在客户端采用的存储方式,置1代表使用cookie记录客户端的sessionid,同时,$_COOKIE变量里才会有$_COOKIE[‘PHPSESSIONID’]这个元素存在)时,浏览器禁用cookie后,是不能使用session的,这个说法也非绝对,在程序中可以让其可以使用,说明如下:

Created with Raphaël 2.2.0 第一次访问网站 服务端脚本中开启Session,session_start(); 服务端生成一个不重复的SESSIONID的文件session_id(); 返回含有如下HTTP头 Set-Cookie:PHPSESSIONID=xxxxxxx 客户端接收到Set-Cookie的头,将PHPSESSIONID写入cookie 第二次访问,所有Cookie会附带着请求头发送给服务端 服务端根据cookie中PHPSESSIONID的值,去session目录查找对应session文件 找到这个session文件后,检查是否过期,若未过期,读取该Session文件中的配置;若已过期,清空其中的配置

根据以上流程,当禁用cookie后(此时,服务端因为没有得到PHPSESSIONID的cookie,会不停的生成session_id文件),PHPSESSIONID都无法生成,自然无法使用session。另外http头部信息可以用getallheaders()函数查看。
但是,在代码中,如果一个Cookie都没接收到,那么代码可以预判客户端禁用了Cookie,那将session_id附带在每个网址后面(包括POST),eg:

GET http://www.xx.com/index.php?session_id=xxxxx
POST http://www.xx.com/post.php?session_id=xxxxx

然后在每个页面的开头使用session_id($_GET['session_id']),来强制设置当前session_id,由此,又是可以使用session的。

附:
在php.ini中session.use_trans_sid=1 ,表示当客户端浏览器禁止cookie的时候,页面上的链接会基于url传递SESSIONID。但是很多人仅仅设置了这一个选项并没有达到效果。
php.ini 文件中还有两个选项
session.use_cookies=1
session.use_only_cookies=1

session.use_cookies表示是否开始基于cookies的session会话
session.use_only_cookies 表示是否只开启基于cookies的session的会话方式

就是说如果session.use_trans_sid=1并且客户端浏览器禁止cookie的时候,达不到效果,就要注意session.use_only_cookies的值是否为0

你可能感兴趣的:(PHP,---php基础系列,php基础)