总字符数: 32.99K

代码: 23.98K, 文本: 6.72K

预计阅读时间: 2.22 小时

八、PHP 数组

数组:array,数据的组合,指将一组数据(多个)存储到一个指定的容器中,用变量指向该容器,然后可以通过变量一次性得到该容器中的所有数据.

创建数组

在 PHP 中,array()函数用于创建数组

在 PHP 中,有三种类型的数组:

  • 数值数组 - 带有数字 ID 键的数组
  • 关联数组 - 带有指定的键的数组,每个键关联一个值
  • 多维数组 - 包含一个或多个数组的数组
1
2
3
4
5
6
7
8
在PHP中系统提供多种定义数组的方式:
1. 使用array关键字:最常用的
$变量= (array元素1,元素2,元素3..);
2. 可以使用中括号来包裹数据:
$变量 = [元素1,元素2...];
3. 隐形定义数组:给变量增加一个中括号,系统自动变成数组
$变量[]=值1; //如果不提供下标也可以,系统自动生成(数字:从0开始)
$变量[下标]=值; //中括号里面的内容称之为下标key,该下标可以是字母(单词)或者数字,与变量命名的规则相似
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
// 数值数组
$array_num=array("php","java","python");
$array_num1=array();
$array_num1[0]="php";
$array_num1[1]="java";
$array_num1[2]="python";
var_dump($array_num);
echo "</br>";
var_dump($array_num1);
echo "</br>";
// 关联数组
$array_key=array("姓名"=>"张三","成绩"=>100,"班级"=>"2班");
$array_key1=array();
$array_key1["姓名"]="张三";
$array_num1["成绩"]=100;
$array_num1["班级"]="2班";
var_dump($array_key);
echo "</br>";
var_dump($array_key1);

多维数组

多维数组是包含一个或多个数组的数组.

在多维数组中,主数组中的每一个元素也可以是一个数组,子数组中的每一个元素也可以是一个数组.

数组的维度指示您需要选择元素的索引数.
  • 对于二维数组,您需要两个索引来选取元素
  • 对于三维数组,您需要三个索引来选取元素

在第二维度的数组元素中可以继续是数组,在PHP中没有维度限制(PHP本质并没有二维数组),但是不建议使用超过三维以上的数组,会增加访问的复杂度,降低访问效率.

两维数组

两维数组是数组的数组(三维数组是数组的数组的数组).

姓名 年龄 性别
php 30
Bob 17
Tony 21
wink 15

如下将上表中的数据存储到两维数组中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// 多维数组
$user = array
(
array("php",30,"男"),
array("Bob",15,"女"),
array("Tony",5,"男"),
array("Wink",17,"女")
);
/*
* 现在这个两维数组包含了四个数组,并且它有两个索引(下标):行和列.
* 如需访问 $user 数组中的元素,我们必须使用两个索引(行和列):
*/
echo $user[0][0].":年龄 :".$user[0][1].", 性别:".$user[0][2].".<br>";
echo $user[1][0].":年龄 :".$user[1][1].", 性别:".$user[1][2].".<br>";
echo $user[2][0].":年龄 :".$user[2][1].", 性别:".$user[2][2].".<br>";
echo $user[3][0].":年龄 :".$user[3][1].", 性别:".$user[3][2].".<br>";

数组的常用操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
$fruits = array('apple', 'banana', 'orange');
// 添加新元素到数组开头
array_unshift($fruits,"tomato");
print_r($fruits);
echo "</br>";
// 添加新元素到数组末尾
$fruits[]="peach";
print_r($fruits);
echo "</br>";
// 合并两个数组
$fruits2 = array('blueberry', 'grape');
print_r(array_merge($fruits,$fruits2));
echo "</br>";
// 反转数组
print_r(array_reverse($fruits));
echo "</br>";
// 获取数组中的所有键名或所有值
print_r(array_keys($fruits));
echo "</br>";
print_r(array_values($fruits));
echo "</br>";
// 检查一个值是否在数组中,并返回对应的键名
echo "根据值搜索键名:".array_search("grape",$fruits2);
echo "</br>";
// 修改数组元素值
$fruits2[1]="apricot";
print_r("修改数组元素值:".$fruits2);
echo "</br>";
// 检查数组中是否存在某个元素
var_dump("检查数组中是否存在某个元素:".in_array("apple",$fruits));
echo "</br>";
// 获取数组的长度(元素个数)
echo "数组长度:".count($fruits);
echo "</br>";
// 检查数组是否为空
var_dump(empty($fruits));

PHP数组特点

  1. 可以整数下标或者字符串下标
  2. 不同下标可以混合存在
  3. 数组元素的顺序以放入顺序为准,跟下标无关
  4. 数字下标的自增长性
    • 从0开始自动增长,如果中间手动下标出现较大的,那么后面的自增长元素从最大的值+1开始
  5. 特殊值下标的自动转换
    • 布尔值
      • true
      • false
      • null
  6. PHP中数组元素没有类型限制
  7. PHP中数组元素没有长度限制

PHP中的数组是很大的数据,所以存储位置是堆区,为当前数组分配一块连续的内存.

1
2
3
4
5
<?php
$arr1[false]=false;
$arr1[true]=true;
$arr1[null]=null;
var_dump($arr1);

数组遍历

数组遍历:普通数组数据的访问都是通过数组元素的下标来实现访问,如果说数组中所有的数据都需要依次输出出来,就需要我们使用到一些简化的规则来实现自动获取下标以及输出数组元素.

1
2
3
4
5
6
7
$arr = array(0=>array('name'=>'Tom'),1=>array('name'=>'Jim'));  //二维数组

// 访问一维元素:$arr[一维下标]
$arr[0]; //结果:array('name'=>'Tom');

//访问二维元素:$arr[一维下标][二维下标]
$arr[1]['name'];//结果:Jim

foreach

遍历原理

foreach遍历的原理:本质是数组的内部有一颗指针,默认是指向数组元素的第一个元素,foreach就是利用指针去获取数据,同时移动指针.

1
2
3
4
5
6
7
foreach($arr, as $k => $v){
//循环体
}
# 1.foreach会重置指针:让指针指向第一个元素;
# 2.进入foreach循环:通过指针取得当前第一个元素,然后将下标取出放到对应的下标变量$k中(如果存在),将值取出来放到对应的值变量$v中;(指针下移)
# 3.进入到循环内部(循环体),开始执行;
# 4.重复2和3,直到在2的时候遇到指针取不到内容(指针指向数组最后)
遍历语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
/*
基本语法:
foreach(数组变量 as [$下标=>] $值){
}
通常:如果是关联数组(字母下标),就需要下标,如果是数字下标就直接访问值

在进行数据存储定义的时候,通常二维数组不会两个维度的key下标都为数字,一般是一维为数字(无意义),二维为字符串(数据库表字段),所以在进行遍历的时候,通常是只需要针对一维进行遍历,取得二维数组元素,然后二维数组元素通过下标去访问.
*/
$arr = ['a' => 'aaa', 'b' => 'bbb', 'c' => 'ccc'];
// 使用 foreach 遍历数组,并将键名赋值给 $key,键值赋值给 $value
foreach ($arr as $key => $value) {
echo $key . '<br/>'; // 输出当前的键名
}
echo "--------";
echo "</br>";
// 使用 foreach 遍历数组,只获取键值部分,赋值给 $val
foreach ($arr as $val) {
echo $val . '<br/>'; // 输出当前的键值
}

for循环遍历数组

for循环:基于已知边界条件(起始和结束)然后有条件的变化(规律)
因此:for循环遍历数组有对应条件

  1. 获取数组长度:count(数组)得到数组元素的长度
  2. 要求数组元素的下标是规律的数字
1
2
3
4
5
6
7
8
$arr = array(1, 2, 3, 4, 5, 6, 7, 10);
// 获取数组的长度(元素个数)
$len = count($arr);
// 使用 for 循环从数组的第一个元素开始遍历到最后一个元素
for ($i = 0; $i < $len; $i++) {
// 输出当前的键(下标) $i,以及对应的值 $arr[$i]
echo 'key is :', $i, ' and value is :', $arr[$i], '</br>';
}

数组排序函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
1. 排序函数:对数组元素进行排序,都是安装ASCII码进行比较,可以进行英文比较
sort():顺序排序(下标重排)
asort():升序排序(对键排序)
rsort():逆序排序
asor():顺序排序(下标保留)
arsort():逆序排序
ksort():顺序排序:按照键名(下标)
krsort():逆序排序
shuffle():随机打乱数组元素,数组下标会重排
2. 指针函数
reset():重置指针,将数组指针回到首位
end():重置指针,将数组指针指到最后一个元素
next():指针下移,取得下一个元素的值
prev():指针上移,取得上一个元素的值
current():获取当前指针对应的元素值
key():获取当前指针对应的下标值
注意事项:next和prev会移动指针,有可能导致指针移到最前或者最后(离开数组),导致数组不能使用,不能通过next和prev不能回到正确的位置.只能通过end或者reset进行指针重置
3. 其他函数
count():统计数组中元素的数量
array_push():往数组中加入一个元素(数组后面)
array_pop():从数组中取出一个元素(数组后面)
array_shift():从数组中取出一个元素(数组前面)
array_unshift():从数组中加入一个元素(数组前面)
PHP模拟数据结构:
栈:压栈,先进去后出来(FILO)

//数据结构:栈和队列
$arr = array();
//栈:先压栈后出栈:都是从一端出来
//前面:array_shift/array_unshift
//后面:array_push/array_pop
//压栈
array_push($arr,3);
array_push($arr,2);
array_push($arr,1);
print_r($arr);
//出栈
echo array_pop($arr),array_pop($arr),array_pop($arr);
结果:
Array
(
[0] => 3
[1] => 2
[2] => 1
)
123

队列:排队,先进去的先出去(FIFO)
//队列:先排队,先出来,一端进,另外一端出
//后进前出:array_push/array_shift
//前进后出:array_unshift/array_pop
$arr = array();
//入队
array_unshift($arr,3);
array_unshift($arr,2);
array_unshift($arr,1);
print_r($arr);
//出队
echo array_pop($arr),array_pop($arr),array_pop($arr);

arcray_reverse():数组元素反过来
in_array():判断一个元素在数组中是否存在
array_keys():获取一个数组的所有下标,返回一个索引数组
array_values():获取一个数组的所有值,返回一个索引数组

九、PHP 循环

在日常编写代码时,经常需要让相同的代码块一次又一次地重复运行.我们可以在代码中使用循环语句来完成这个任务.

在 PHP 中,提供了下列循环语句:

  • while - 只要指定的条件成立,则循环执行代码块
  • do…while - 首先执行一次代码块,然后在指定的条件成立时重复这个循环
  • for - 循环执行代码块指定的次数
  • foreach - 根据数组中每个元素来循环代码块

while 循环

while 循环将重复执行代码块,直到指定的条件不成立

1
2
3
4
5
条件初始化;
while(条件表达式){
//条件表达式就是判断边界条件
循环体;//循环条件的变化
}
1
2
3
4
5
6
<?php
$i = 1; // 初始化变量$i为1
while ($i <= 5) { // 当$i小于等于5时执行循环
echo "num is " . $i . "<br>"; // 输出当前的$i值
$i++; // 增加$i的值,以便进行下一次循环
}

do…while 语句

do-while:看着很像while,while首先进行条件判定然后执行循环体,有可能出现第一次就条件不满足,那么就会直接失败(循环体一次都不执行).

do-while就是先干了再说(先执行循环体).后判断条件(至少会执行一次循环体)

1
2
3
do{
循环体;
}while(条件表达式);
1
2
3
4
5
6
<?php
$i=1;
do{
$i++;
echo "num " . $i . "<br>";
}while ($i<=5);

for 循环

for 循环用于您预先知道脚本需要运行的次数的情况

1
2
3
4
5
6
for(初始值;条件;增量){
//初始值:定义初始化条件,可以有多种赋值语句存在,使用逗号分隔即可
//条件:边界判定,限定循环执行的次数
//增量:用来执行条件变化
//循环体
}

参数:

  • 初始值:主要是初始化一个变量值,用于设置一个计数器(但可以是任何在循环的开始被执行一次的代码).
  • 条件:循环执行的限制条件.如果为 TRUE,则循环继续.如果为 FALSE,则循环结束.
  • 增量:主要用于递增计数器(但可以是任何在循环的结束被执行的代码).
上面的初始值和增量参数可为空,或者有多个表达式(用逗号分隔).
1
2
3
4
5
<?php
for ($i=1; $i<=5; $i++)
{
echo "num is " . $i . "<br>";
}

foreach 循环

foreach 循环用于遍历数组,我们在数组那一章讲了

循环控制

中断控制和终止控制是用于控制程序流程的重要工具.

  1. 中断控制: 中断控制是指在程序执行过程中,根据某些条件或事件的发生,提前跳出当前代码块或循环,并转移到事先定义好的处理逻辑.中断控制可以帮助我们及时处理特定的情况,提高程序的灵活性和健壮性.

    常见的中断控制包括使用break关键字来中断循环或跳出代码块.break语句可以用于终止当前的循环结构(例如forwhiledo-while)或switch语句.

  2. 终止控制: 终止控制是指在程序执行过程中,根据某些条件或事件的发生,立即终止整个程序的执行.通常情况下,终止控制被视为异常情况的处理方式,用于在程序出现严重错误或无法继续执行时停止程序的运行.

    在PHP中,我们可以使用exitdie函数来实现终止控制.这两个函数可以立即终止当前脚本的执行,并返回一个指定的退出码.它们还可以输出一条可选的终止消息.

在编写代码时,需要注意以下几点:

  • 中断控制通常用于在满足特定条件时跳出循环或代码块,提前结束当前的执行流程.
  • 终止控制应该谨慎使用,只在程序无法继续执行或出现严重错误的情况下才使用.过度使用终止控制可能会导致程序
  • 结构混乱或在调试时难以追踪问题.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
// continue用于跳过当前循环中剩余的代码,并继续下一次循环的执行.
// continue的使用场景通常是在循环结构内部,用于满足某些条件时跳过当前迭代并进入下一次迭代.当程序执行到continue语句时,它会立即跳过当前循环体内后续的代码,然后返回至循环结构的开始处,检查循环条件并决定是否进入下一次循环.
$i = 1; // 初始化变量$i为1
while ($i <= 100) {
// 在 $i 小于等于 100 的条件下循环执行以下代码块
// 判断: 是否是 5 的倍数
if ($i % 5 != 0) {
// 若 $i 不是 5 的倍数
$i++; // 增加 $i 的值,继续下一次循环
// 重新循环
continue; // 系统重新跳到循环开始处
}
// 输出数值
echo $i++, '<br/> '; // 输出当前 $i 的值,并增加 $i 的值,显示换行标签 <br/>
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
// break用于中断循环结构的执行,并跳出当前循环
// break的使用场景通常是在循环结构内部,当满足某些条件时提前结束整个循环.当程序执行到break语句时,它会立即退出当前的循环体,并继续执行循环后面的代码.
// 需要注意的是,break语句只能中断离它最近的循环结构.也就是说,break语句只会中断包含它的最内层循环,不会影响外层的循环.
$i = 1;
while ($i <= 100) {
// 判断: 是否是5的倍数
if ($i % 5 != 0) {
// 说明当前$i不是5的倍数
$i++; // 输出当前的$i值,并且将$i自增1
// 终止循环
break;
}
}
echo $i; // 为什么结果是2呢?
/*
Continue 2;//当前自己循环后面内部不再执行,同时外部循环如果还有循环体也不再执行,重新来过;
Break 2;//当前自己循环结束,同时外部也结束(如果还有外部(第三层)不受影响,继续执行)
*/

流程控制替代语法

流程控制替代语法:分支和循环结构的替代语法

PHP本身是嵌入到HTML中的脚本语言,需要在HTML中书写一些关于判断或者循环的结构语法,必须符合PHP标签规范,需要 HTML与 PHP进行混搭,如果使用原始的PHP代码那么会非常不美观.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<table border=1>
<?php for($i = 1;$i < 10;$i++){?>
<tr>
<?php for($j = 1;$j < $i;$j++){?>
<td>
<?php echo $j .'*' .$i . '= ' .$i*$j;?>
</td>
<?php }?>
</tr>
<?php } ?>
</table>
// 在PHP书写到HTML中的这些大括号}非常不美观,所以PHP提供了一种替代机制,让其可以不用书写大括号:
for(;;){ => for(;;):
} =>endfor;
如下:
<table border=1>
<?php for($i = 1;$i < 10;$i++):?>
<tr>
<?php for($j = 1;$j < $i;$j++):?>
<td>
<?php echo $j .'*' .$i . '= ' .$i*$j;?>
</td>
<?php endfor;?>
</tr>
<?php endfor; ?>
</table>

十、PHP 函数

​ PHP函数是一段封装了特定功能的可重复使用的代码块.它们可以接受参数并返回值,用于执行特定任务或实现特定操作.函数的使用可以大大提高代码的可读性、重用性和维护性.

​ 在PHP中,你可以使用内置的函数,也可以自定义函数来满足特定的需求.内置函数如strlen()用于获取字符串长度,array_push()用于向数组末尾添加元素等等.通过自定义函数,你可以根据具体需求编写自己的函数,并在需要的时候调用它们.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
以下是PHP的内置函数,用于检测变量的数据类型,以及它们的语法、用法及相关注释的举例:

1. is_array() //判断变量是否为数组

// 语法
bool is_array(mixed $var)

// 用法
$var = array('apple', 'orange', 'banana');
echo is_array($var) ? 'Array' : 'Not an Array'; // 输出:Array


2. is_bool() //判断变量是否为布尔值

// 语法
bool is_bool(mixed $var)

// 用法
$var = false;
echo is_bool($var) ? 'Boolean' : 'Not a Boolean'; // 输出:Boolean


3. is_float() //判断变量是否为浮点数

// 语法
bool is_float(mixed $var)

// 用法
$var = 1.234;
echo is_float($var) ? 'Float' : 'Not a Float'; // 输出:Float


4. is_int() //判断变量是否为整数

// 语法
bool is_int(mixed $var)

// 用法
$var = 3;
echo is_int($var) ? 'Integer' : 'Not an Integer'; // 输出:Integer


5. is_null() //判断变量是否为NULL

// 语法
bool is_null(mixed $var)

// 用法
$var = null;
echo is_null($var) ? 'NULL' : 'Not NULL'; // 输出:NULL


6. is_numeric() //判断变量是否为数字或者数字字符串

// 语法
bool is_numeric(mixed $var)

// 用法
$var = '123';
echo is_numeric($var) ? 'Numeric' : 'Not Numeric'; // 输出:Numeric


7. is_object() //判断变量是否为对象

// 语法
bool is_object(mixed $var)

// 用法
$var = new stdClass;
echo is_object($var) ? 'Object' : 'Not an Object'; // 输出:Object


8. is_resource() //判断变量是否为资源类型

// 语法
bool is_resource(mixed $var)

// 用法
$var = fopen("text.txt", "r");
echo is_resource($var) ? 'Resource' : 'Not a Resource'; // 输出:Resource


9. is_string() //判断变量是否为字符串

// 语法
bool is_string(mixed $var)

// 用法
$var = "Hello World!";
echo is_string($var) ? 'String' : 'Not a String'; // 输出:String
// 注: 如果直接打印结果,成功显示为1,失败则不打印任何内容

​ 使用函数可以将复杂的任务分解为更小的可管理单元,使代码更加模块化.这使得代码更易于理解、调试和修改.此外,PHP还提供了许多有用的内置函数和函数库,以便更方便地处理各种任务,如字符串处理、文件操作、数据库连接等.

​ 为了使用函数,你需要先定义函数并指定函数名、参数列表和函数体.函数名应具有描述性,能够清楚地表达函数的功能.参数列表定义了函数接受的输入,而函数体则包含了要执行的代码.当需要使用函数时,只需调用函数并传递所需的参数即可.

创建 PHP 函数

1
2
3
4
5
6
<?php
// function 定义函数的关键字
function functionName([参数]){ //[参数]可有可无
//函数体
//返回值: return结果;
}

函数命名规范:

  1. 函数名不区分大小写
  2. 函数名使用英文,遵循规范
  3. 下划线不属于特殊符号
  4. 数字可以加在中间或者后面
  5. 不用特殊符号
  6. 命名的时候要有意义
  7. 遵循驼峰或者下划线
  8. 不能使用系统函数以及关键字作为函数名

如下创建一个输出一句话的函数:

1
2
3
4
5
6
<?php
function echo_test()
{
echo "PHP study hard !! ";
}
echo_test();

输出结果:

1
PHP study hard !!

函数 - 添加参数

​ 在PHP函数中,添加参数是指在函数定义时声明函数所需的输入.参数允许你向函数传递数据,使函数能够处理不同的输入并产生相应的输出.

​ 在函数定义中,你可以指定零个或多个参数,每个参数由参数名和参数类型组成.参数名是用来在函数内部引用输入值的变量名,而参数类型则决定了该参数接受的数据类型.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
function name($names)
{
echo $names . "<br>";
}

echo "My name is ".name("php");
echo "My sister's name is ".name("Bob");
echo "My brother's name is ".name("Tony");
echo "-------------------</br>";
// 指定类型的参数
function type_name(string $type_names){
var_dump($type_names);
echo "</br>";
echo $type_names. "</br>";
}
echo "My name is ".type_name("php");
echo "My sister's name is ".type_name(100); // 函数会自动强制帮我们转换成string类型
echo "My brother's name is ".type_name("Tony");

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
// 参数默认值
/*
* PHP 中的函数参数默认值允许你在函数定义中为参数指定一个默认的数值或者字符串.
* 这意味着如果函数在调用时没有为该参数提供值,那么将会使用默认值作为参数的值.
* 参数默认值的设置使得函数更加灵活,因为你不需要每次都为每个参数提供值.
* 使用参数默认值非常简单,只需要在函数定义中为参数赋予默认值即可
* */

/*
* 如果你为函数的参数设置默认值,则所有没有默认值的参数必须位于有默认值的参数之前.
* 这是由 PHP 语法规则所决定的.
* 这个限制存在的原因是为了确保代码的可读性和可预测性.
* 当函数的参数有默认值时,调用函数时可以省略这些参数.
* 如果允许将拥有默认值的参数放在第一个位置,那么在省略其他参数时,很难确定哪些参数被省略了
* 从而导致代码不易阅读和理解.
* */
function greet($name,$age=100) {
echo "Hello, " . $name.",年龄:".$age;
}

greet("Guest"); // 输出: Hello, Guest,年龄:100
greet("John",10); // 输出: Hello, John,年龄:10

函数返回值

​ 函数返回值是指函数执行完成后,将结果返回给调用者的值.

​ 以下是一段介绍 PHP 函数中函数返回值的内容:

​ PHP 中的函数返回值允许你从函数中获取一个结果,并将该结果传递给调用函数的代码.使用函数返回值可以使函数更加灵活和实用,因为你可以利用函数的返回值来进行进一步的操作、处理和判断.

​ 要在 PHP 中使函数返回一个值,你可以使用 return 语句.在函数的代码块中,当需要返回值时,可以使用 return 关键字后跟要返回的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
// 返回值只有1个

// 定义一个名为 calculateSum 的函数,接受两个参数 $num1 和 $num2
function calculateSum($num1, $num2) {
return $num1 + $num2; // 返回两个参数的和
}
// 调用 calculateSum 函数,传入参数 5 和 3,并将结果赋值给 $result 变量
$result = calculateSum(5, 3);
// 输出结果: 8,并在输出后添加 HTML 换行标签
echo $result."</br>";

// 返回值有多个 可以将这些值封装到数组或对象中,然后将该数组或对象作为函数的返回值.
// 定义一个名为 getPersonInfo 的函数,返回一个包含个人信息的数组
function getPersonInfo(): array {
$name = "John"; // 声明并赋值变量 $name,存储名字 "John"
$age = 25; // 声明并赋值变量 $age,存储年龄 25
$occupation = "Developer"; // 声明并赋值变量 $occupation,存储职业 "Developer"
return array($name, $age, $occupation); // 返回一个包含个人信息的数组
}

$info = getPersonInfo(); // 调用 getPersonInfo 函数,并将返回的数组赋值给变量 $info

echo $info[0]."</br>"; // 输出数组 $info 的第一个元素,即名字 "John"
echo $info[1]."</br>"; // 输出数组 $info 的第二个元素,即年龄 25
echo $info[2]."</br>"; // 输出数组 $info 的第三个元素,即职业 "Developer"

回调函数

在PHP中,回调函数是一种可以作为参数传递给其他函数的函数.回调函数在函数内部被调用,允许在特定的时候执行自定义的代码逻辑.使用回调函数可以实现更灵活、可扩展的代码结构.

为什么使用回调函数?

使用回调函数的主要目的是将某些代码逻辑作为参数传递给其他函数,以便在特定的时候执行.这样做的好处包括:

  • 提供了解耦的方式:回调函数将代码逻辑与主函数分离,使得代码更易于理解和维护.
  • 增强了代码的灵活性:通过动态设置回调函数,可以根据需要改变函数的行为.
  • 实现了代码的复用:可以将相同的回调函数应用于多个函数调用,避免了重复编写相似的代码.

如何使用回调函数?

使用回调函数需要注意以下几点:

  1. 定义回调函数:首先,需要定义一个函数,作为回调函数的具体实现.该函数可以是普通函数、类方法或匿名函数.
  2. 将回调函数作为参数传递:在调用支持回调的函数时,将回调函数作为参数传递给这些函数.确保回调函数的参数和返回值与被调用的函数要求的一致.
  3. 执行回调函数:当被调用的函数满足特定条件时,会在适当的时候执行传递的回调函数.

示例代码

回调函数示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
/**
* 函数 process() 接受两个参数:$data 和 $callback.
* 它执行一些处理操作后,调用传递的回调函数 $callback 并将 $data 作为参数传递给回调函数.
* 最后,函数 process() 返回回调函数的结果.
*/

function process($data, $callback)
{
// 执行某些处理操作
// 调用回调函数
$result = $callback($data);
// 继续处理其他操作
return $result;
}

/**
* 回调函数 myCallback() 接收一个参数,并将该参数乘以2后返回.
*/
function myCallback($value)
{
return $value * 2;
}

$data = 10;
// 调用函数 process() 并传递回调函数 myCallback()
$result = process($data, 'myCallback');

echo $result; // 输出:20

可变函数

可变函数:当前有一个变量所保存到值,刚好是一个函数的名字,那么就可以使用变量+()来充当函数名使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
/*
* $变量='display';
* function display(){
* }
* //可变函数
* $变量()
* */

// 定义一个名为 display 的函数,用于输出函数名
function display(){
echo __FUNCTION__."</br>"; // 输出函数的名称,并添加 HTML 换行标签
}
$func = "display"; // 将字符串 "display" 赋值给变量 $func
display(); // 调用 display 函数,输出函数的名称
$func(); // 使用变量 $func 来调用函数,输出函数的名称

可变函数在系统使用的过程中还是比较多的,尤其是使用很多系统函数的时候:需要用户在外部定义一个自定义函数,但是是需要传入到系统函数内部使用.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// 代码示例:
// 将一个用户定义的函数传入给另外一个函数(函数名)去使用的过程,称之为回调过程,而被传入的函数称之为回调函数
//定义系统函数(假设)
function sys_function($arg1,$arg2){
//给指定的函数(第一个参数),求对应的第二个参数值的4次方
//对实际用户输入的数值进行处理
$age2 = $age2 + 10;
return $arg1($arg2); //相当于user_function(20)
}
//定义一个用户函数:求一个数的四次方
function user_function($num){
return $num * $num * $num * $num;
}

//求10的4次方
sys_function('user_function',10);

匿名函数

在PHP中,匿名函数是一种没有明确命名的函数,也称为闭包函数.可以通过使用function()语法来创建匿名函数.匿名函数通常用于以下场景: - 作为回调函数传递给其他函数.

在需要一个短暂的函数时,不必为其命名.

创建匿名函数的一般语法如下:

1
2
3
4
5
6
7
8
9
<?php
/*
* $anonymous是变量名,可以根据需要自行定义.
* parameters是匿名函数的参数.
* 函数体中可以编写实际要执行的代码逻辑.
*/
$anonymous = function(parameters) {
// 函数体
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
/*
* 匿名函数可以像普通函数一样被调用.
* 如果要执行匿名函数,可以像调用普通函数一样使用变量名加括号的方式.
*/
$sum = function($a, $b) {
return $a + $b;
};
echo $sum(2, 3); // 调用匿名函数并传递参数

/*
* 匿名函数还可以作为回调函数传递给其他函数
* 例如array_map()和usort()等PHP函数.
* */
$numbers = [1, 2, 3, 4, 5]; // 定义了一个数字数组 $numbers,包含了数字 1 到 5.

// 使用匿名函数作为回调函数,对数组中的每个元素进行平方操作
/*
* array_map() 是一个PHP内置函数,用于将回调函数应用到给定数组中的每个元素,
* 并返回一个新的数组,其中包含了应用回调函数后的结果.
* 语法:
* array_map(callback $callback, array $array1, array ...$arrays): array
* callback:回调函数,可以是普通函数、类方法或匿名函数.
* $array1, $arrays:要操作的数组,可以是一个或多个数组.
* */
/*
*
* 使用 array_map() 函数对数组 $numbers 中的每个元素应用回调函数来进行平方操作.
* 匿名函数被传递给 array_map() 函数作为回调函数,它采用一个参数 $number,表示数组中的当前元素,然后返回该元素的平方值.所以,匿名函数内部使用 $number * $number 来计算平方.
* array_map() 函数返回一个新的数组,其中包含了对原始数组 $numbers 中的每个元素进行平方操作后的结果.
* */
$squared = array_map(function($number) {
return $number * $number;
}, $numbers);

print_r($squared); // 输出:Array ( [0] => 1 [1] => 4 [2] => 9 [3] => 16 [4] => 25 )

变量保存匿名函数,本质得到的是一个对象(closure)

1
2
3
4
5
6
7
<?php
$sum = function($a, $b) {
return $a + $b;
};
echo $sum(2, 3); // 调用匿名函数并传递参数
echo "</br>";
var_dump($sum); // object(Closure)#1 (1) { ["parameter"]=> array(2) { ["$a"]=> string(10) "" ["$b"]=> string(10) "" } }

闭包(Closure)

在PHP中,闭包是一种特殊的匿名函数,它可以在定义时捕获其周围作用域的变量,并且可以在后续的调用中访问和修改这些变量.闭包允许我们将函数作为一等公民来对待,可以将其作为参数传递给其他函数,也可以从其他函数中返回.

创建闭包

闭包的基本语法如下:

1
2
3
$closure = function ($arg1, $arg2, ...) {
// 函数体
};

通过使用 function 关键字和匿名函数的语法,我们可以创建一个闭包并将其赋值给变量 $closure.闭包可以接收任意数量的参数,并且在函数体中执行相应的操作.

使用闭包

闭包可以像普通函数一样被调用,例如:

1
2
<?php
$result = $closure($value1, $value2);

在上述例子中,我们通过调用闭包 $closure 并传递参数 $value1$value2 来获取结果 $result.闭包会根据传入的参数执行函数体中的操作,并返回一个结果.

捕获变量

闭包不仅可以访问传递给它的参数,还可以捕获定义在其周围作用域中的变量.这意味着闭包可以在稍后的调用中访问和修改这些变量的值.

1
2
3
4
5
6
<?php
$message = "Hello";
$closure = function ($name) use ($message) {
echo $message . ", " . $name;
};
$closure("John"); // 输出:Hello, John

在上述例子中,闭包 $closure 捕获了定义在其周围作用域中的变量 $message.在闭包内部,我们可以通过 use 关键字引用这个变量,并将其用于输出.

应用场景

闭包常常用于回调函数、事件处理程序和高阶函数等场景.它们可以帮助我们编写更灵活和可重用的代码,同时提供更好的封装性和代码组织方式.

闭包和匿名函数的区别

我们的匿名函数明明可以传参为什么还要用到闭包呢?

​ 匿名函数确实可以传递参数,但是闭包是一种特殊的匿名函数,它具有捕获周围作用域变量的能力.

​ 闭包与普通匿名函数的区别在于,闭包可以在定义时捕获其周围作用域中的变量,并且可以在后续的调用中访问和修改这些变量的值.这使得闭包在某些情况下更为灵活和强大.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
// 闭包与普通匿名函数的区别在于,闭包可以在定义时捕获其周围作用域中的变量,并且可以在后续的调用中访问和修改这些变量的值.这使得闭包在某些情况下更为灵活和强大.
// 示例
function createMultiplier($factor) {
return function ($number) use ($factor) {
return $number * $factor;
};
}

$double = createMultiplier(2);
$result = $double(10);
echo $result; // 输出:20
// 我们使用闭包创建了一个乘法器函数 createMultiplier(),它接受一个因子参数并返回一个闭包.这个闭包将捕获 createMultiplier() 函数的 $factor 参数,并返回给定数值和因子的乘积.

​ 通过这种方式,闭包可以更灵活地操作作用域中的变量.

​ 即使在定义闭包时,外部变量的值已经发生了改变,闭包仍然可以访问到最初捕获的变量值.

​ 因此,捕获参数是指闭包在定义时绑定并保留对周围作用域变量的引用,以便在后续调用中使用,而传参是指直接向匿名函数传递参数来处理特定的操作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
// 以下代码用于解释定义闭包时,外部变量的值已经发生了改变,闭包仍然可以访问到最初捕获的变量值
$factor = 2;
$factor2 = 10;
$greeting = function ($number,$factor) {
return $number * $factor;
};

echo $greeting($factor2,$factor); // 输出:Hello, John
echo "</br>";
$factor = 10;
echo "读的是新的值:".$greeting($factor2,$factor); // 输出:Hello, John
echo "</br>";


$factor = 2;

$multiplier = function ($number) use ($factor) {
return $number * $factor;
};

$result = $multiplier(10);
echo $result; // 输出:20
echo "</br>";
$factor = 10; // 使变量产生新的值
$result = $multiplier(10);
echo '读的是最初的$factor值:'.$result; // 输出:20

相关函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
字符串相关函数
1. 转换函数: implode(),explode(),st_split()
lmplode(连接方式,数组):将数组中的元素按照某个规则连接成一个字符串,
explode(分割字符,目标字符串):将字符串按照某个格式进行分割,变成数组
str_split(字符串,字符长度):按照指定长度拆分字符串得到数组
2. 截取函数: trim(),ltrim(), rtrim()
trim(字符串,[指定字符]):本身默认是用来去除两边的空格(中间不行),但是也可以指定要去除的内容,是按照指定的内容循环去除两边有的内容:直到碰到一个不是目标字符为止.
ltrim():去除左边的空格
rtrim():去除右边的空格
3. 截取函数: substr(),strstr()
substr(字符串,起始位置从0开始[长度]):指定位置开始截取字符串,可以截取指定长度(不指定到最后)
strstr(字符串,匹配字符):从指定位置开始,截取到最后(可以用来取文件后缀名)
4. 大小转换函数: strtolower(),strtoupper(),ucfirst()
strtolower: 全部小写
strtoupper: 全部大写
ucfirst: 首字母大写
5. 查找函数: strpos(),strrpos()
strpos():判断字符在目标字符串中出现的位置(首次)
strrpos():判断字符在目标字符串中最后出现的位置
6. 替换函数: str_replace()
str_replace(匹配目标,替换的内容,字符串本身):将目标字符串中部分字符串进行替换,
$str = '123a234a3b2a';
str_replace('a','b',$str);
7. 格式化函数: printf(),sprintf()
printf/sprintf(输出字符串有占位符,顺序占位内容):格式化输出数据
$age = 50;
$name = 'TOM';
//格式化输出
echo sprintf("你好,今年我%d岁,我叫%s",$age,$name);
8. 其他: str_repeat(),str_shuffle()
str_repeat():重复某个字符串N次
str_shuffle():随机打乱字符串

十一、PHP日期处理

介绍

日期处理在 Web 开发中非常重要,PHP 提供了丰富的日期函数用于处理与日期和时间相关的操作.

获取当前日期和时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
/*
* date(format, timestamp)
* - 返回指定格式的日期字符串.
* - 可通过第二个参数指定时间戳.
* */
echo date('Y-m-d H:i:s'); // 2023-08-03 09:00:56

/*
* time()
* - 返回当前的Unix时间戳
* */
echo "</br>";
echo time(); // 1691024456

/*
* strtotime(timeString)
* - 将人类可读的时间字符串转换为 Unix 时间戳.
* */
echo "</br>";
echo strtotime('2023-08-03 09:00:56'); // 1691024456

格式化日期和时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* date_format(dateTime, format)
* - 格式化日期和时间对象.
* - 适用于 DateTime 对象.
* */
echo "</br>";
// new DateTime('2023-08-03 09:00:56')表示创建了一个 DateTime 对象,表示日期和时间为 2023 年 8 月 3 日 09:00:56.
echo date_format(new DateTime('2023-08-03 09:00:56'), 'Y-m-d H:i:s'); // 输出 2023-08-03 09:00:56


/*
* date_default_timezone_set(timezone)
* - 设置默认时区
* - 时区列表:https://www.php.net/manual/en/timezones.php
* */
echo "设置默认时区:";
date_default_timezone_set('Africa/Abidjan');
echo date('Y-m-d H:i:s'); // 2023-08-03 01:09:47

日期计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?PHP
/*
* strtotime(timeString, now)
* - 将相对的或绝对的时间字符串转换为 Unix 时间戳.
* - 可选的第二个参数指定基准时间.
* */
echo "</br>";
date_default_timezone_set('Asia/Shanghai');
echo date('Y-m-d H:i:s',strtotime('+1 day')); // 2023-08-04 09:12:41

/*
* date_add(dateTime, interval)
* - 在给定的日期上添加时间间隔.
* - 适用于 DateTime 对象.
* */
echo "</br>";
// 创建一个 DateTime 对象,表示日期和时间为 2023 年 8 月 2 日 17:30:00
$dateTime = new DateTime('2023-08-02 17:30:00');
// 创建一个 DateInterval 对象,表示时间间隔为 1 天
$interval = new DateInterval('P1D');
// 在 DateTime 对象上添加时间间隔,这里是添加了 1 天
$dateTime->add($interval);
// 格式化 DateTime 对象并将其以指定格式输出
echo $dateTime->format('Y-m-d H:i:s');

/*
* date_diff(dateTime1, dateTime2)
* - 计算两个日期之间的差异.
* - 适用于 DateTime 对象.
* */
echo "</br>";
// 创建一个 DateTime 对象,表示日期为 2023 年 8 月 2 日(时间默认为 00:00:00)
$dateTime1 = new DateTime('2023-08-02');
// 创建一个 DateTime 对象,表示日期为 2023 年 8 月 5 日(时间默认为 00:00:00)
$dateTime2 = new DateTime('2023-08-05');
// 计算两个日期对象之间的差异
$interval = date_diff($dateTime1, $dateTime2);
// 格式化并输出两个日期之间的天数差异,使用 %R 表示正负号,%a 表示天数
echo $interval->format('%R%a days');

解析和输出日期字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
echo "</br>--------解析和输出日期字符串--------</br>";
/*
* date_parse(dateString)
* - 解析日期字符串并返回关联数组
* */
print_r(date_parse('2023-08-03 09:20:41')); // Array ( [year] => 2023 [month] => 8 [day] => 3 [hour] => 9 [minute] => 20 [second] => 41 [fraction] => 0 [warning_count] => 0 [warnings] => Array ( ) [error_count] => 0 [errors] => Array ( ) [is_localtime] => )

/*
* strftime(format, timestamp)
* - 格式化日期和时间,支持本地化字符串的替换.
* */
echo "</br>";
// 设置本地化的时区为中文(简体)并使用 UTF-8 编码
setlocale(LC_TIME, 'zh_CN.utf8');
// 使用 strftime 函数将当前时间格式化为指定的字符串格式,%Y 表示年份(四位数),%m 表示月份(两位数),%d 表示日期(两位数),%H 表示小时(24小时制),%M 表示分钟,%S 表示秒数
echo strftime('%Y年%m月%d日 %H:%M:%S', time()); // 2023年08月03日 09:22:10

实际应用示例

以下是一些实际应用示例,展示如何利用 PHP 日期函数处理日期和时间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
// 15.5 实际应用示例
echo "</br>实际应用示例</br>";
// 生成特定格式的日期字符串
echo $date = date('Y-m-d');

// 计算两个日期之间的天数差异
echo "</br>";
// 创建一个 DateTime 对象,表示开始日期为 2023 年 7 月 1 日(时间默认为 00:00:00)
$startDate = new DateTime('2023-07-01');
// 创建一个 DateTime 对象,表示结束日期为 2023 年 7 月 10 日(时间默认为 00:00:00)
$endDate = new DateTime('2023-07-10');
// 计算两个日期对象之间的差异
$interval = date_diff($startDate, $endDate);
// 格式化并输出两个日期之间的天数差异,使用 %R 表示正负号,%a 表示天数
echo $interval->format('%R%a days');

// 解析复杂的日期字符串
echo "</br>";
// 定义日期字符串
$dateString = '2023-08-02 17:30:00';
// 使用 date_parse 函数解析日期字符串并返回日期信息数组
$dateInfo = date_parse($dateString);
// 输出解析后的日期信息
echo "年份:" . $dateInfo['year'] . "<br>";
echo "月份:" . $dateInfo['month'] . "<br>";
echo "日期:" . $dateInfo['day'] . "<br>";
echo "小时:" . $dateInfo['hour'] . "<br>";
echo "分钟:" . $dateInfo['minute'] . "<br>";
echo "秒钟:" . $dateInfo['second'] . "<br>";
/*
* result:
* 年份:2023
* 月份:8
* 日期:2
* 小时:17
* 分钟:30
* 秒钟:0
*

总结

PHP 提供了丰富的日期处理函数,用于获取、格式化、计算和解析日期和时间.熟练掌握这些函数可以简化日期处理任务,提高开发效率.

十二、文件包含

文件包含简介

文件包含:在一个 PHP脚本中,需要将另外一个文件(PHP)包含进来,去合作完成一件事情.

文件包含的意义:

  1. 要么使用被包含文件中的内容,实现代码的共享(重用):向上包含(索要)

    1. 向上包含:在当前脚本要用某个代码之前包含别的文件
  2. 要么自己有东西可以给别的文件使用,实现代码的共享(重用):向下包含(给予)

    1. 向下包含:在自己有某个东西的时候,需要别的脚本来显示(自己代码写完之后包含其他文件)

最大的作用:分工协作,每个脚本做的事情不一样,因此可以使用协作方式,让多个脚本共同完成一件事情

解耦和耦合

解耦和耦合是两个重要的概念.

  1. 解耦是指减少模块之间的依赖关系,使得软件的各个模块能够独立地进行修改、测试和维护.
  2. 耦合则是指模块之间的紧密关联程度,高耦合表示一个模块对其他模块的依赖程度较高.

解耦的好处包括:

  1. 提高可维护性:当一个模块独立于其他模块时,修改一个模块不会对其他模块产生影响,从而降低了维护的复杂性.
  2. 增强可测试性:独立的模块可以更容易地进行单元测试,而不需要涉及到其他模块.
  3. 促进团队合作:解耦可以使团队成员并行开发不同的模块,减少彼此之间的阻塞和依赖.

以下是一些常见的解耦策略:

  1. 使用接口或抽象类:通过定义接口或抽象类,模块之间只依赖于接口或抽象类而不是具体实现,从而实现解耦.
  2. 使用事件驱动架构:通过发布-订阅模式或观察者模式,模块之间通过事件进行通信,解耦了发送者和接收者.
  3. 使用依赖注入:将依赖关系从模块内部移动到外部,通过依赖注入容器来管理依赖关系,从而实现解耦.
  4. 使用消息队列:模块通过在消息队列中发送和接收消息进行通信,从而实现解耦.

另一方面,耦合度高的代码容易引发以下问题:

  1. 修改一个模块可能会影响到其他模块,导致意想不到的副作用.
  2. 难以进行单元测试,需要涉及到多个相关模块.
  3. 增加了代码的复杂性和维护成本.

文件包含四种形式

  1. include:包含文件
  2. include_once:系统会自动判断文件包含过程中,是否已经包含过(一个文件最多被包含一次)
  3. require:与include相同
  4. require_once:与include_once相同

文件包含使用

1
2
3
4
5
6
7
8
9
10
11
12
<?php
// 包含基本语法
include '文件名字';
include('文件名字'); //文件名字,注意路径
// 向上包含:先包含文件,后使用文件的内容
include 'include1.php';
echo $a;
echo $b;
// 向下包含:包含文件为了显示以上数据
$a = 10;
const PI = 3.14;
include_once 'include4.php'

文件加载原理

  1. 在文件加载(include或者require)的时候,系统会自动将被包含文件中的代码相当于嵌入到当前文件中
  2. 加载位置:在哪加载,对应的文件中的代码嵌入的位置就是对应的include位置
  3. 在PHP中被包含的文件是单独进行编译的

包含实例

message.php
1
2
<?php 
$message = "php study hard!!!";
show.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SecHub</title>
</head>
<body>

<p>努力学习</p>
<?php include 'message.php';
echo $message;
?>

</body>
</html>

区别总结

  1. include()函数:该函数会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制include()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞.
  2. require()函数:该函数与include()函数类似,也会将指定文件包含到当前PHP文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制require()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞.
  3. include_once()require_once()函数:这两个函数与include()函数和require()函数类似,也会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码.
    • 不同之处在于,如果文件已经被包含过,则不会再次包含.攻击者可以利用这两个函数的特性,通过改变包含文件的路径,来实现文件包含漏洞.
1
2
3
4
5
6
<?php
include('login.php')
echo 'include test final!';//include报错,但是会继续执行,显示:include test final!
require('login1.php')
echo 'require test final!';//require报错,停止代码的执行
?>

十三、PHP 文件操作

简介

在 PHP 中,文件操作是一项非常重要的任务.它允许我们读取文件的内容、写入新的内容,以及对文件进行其他操作.PHP 提供了一组内置函数,使得文件操作变得简单而高效.

作用

文件操作在 Web 开发中有广泛的应用.它可以用于读取配置文件、日志记录、数据存储等场景.通过使用 PHP 的文件操作功能,我们可以方便地处理文件,实现各种需求.

使用场景

  • 读取日志文件并进行数据分析和处理
  • 从配置文件中读取各种设置和参数
  • 将用户提交的表单数据写入到文件中
  • 处理上传的文件,保存到指定目录
  • 读取和修改 CSV、JSON、XML 等格式的数据文件

示例

模式 描述
r 只读.在文件的开头开始.
r+ 读/写.在文件的开头开始.
w 只写.打开并清空文件的内容;如果文件不存在,则创建新文件.
w+ 读/写.打开并清空文件的内容;如果文件不存在,则创建新文件.
a 追加.打开并向文件末尾进行写操作,如果文件不存在,则创建新文件.
a+ 读/追加.通过向文件末尾写内容,来保持文件内容.
x 只写.创建新文件.如果文件已存在,则返回 FALSE 和一个错误.
x+ 读/写.创建新文件.如果文件已存在,则返回 FALSE 和一个错误.
如果 fopen() 函数无法打开指定文件,则返回 0 (false)。

下面是一个示例,展示了如何使用 PHP 进行文件读写操作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
// 定义要读取和写入的文件路径
$filePath = 'D:\\Software\\phpstudy_pro\\WWW\\localhost\\example.txt';

// 打开文件进行写入
$file = fopen($filePath, 'w');

// 检查文件是否成功打开
if ($file) {
// 要写入的内容
$newContent = "这是新的文件内容";

// 写入文件
fwrite($file, $newContent);

// 关闭文件
fclose($file);

echo "文件写入成功!";
} else {
// 文件打开失败
echo "文件打开失败!";
}

// 打开文件进行读取
$file = fopen($filePath, 'r');

// 检查文件是否成功打开
if ($file) {
// 读取文件内容
$content = fread($file, filesize($filePath));

// 关闭文件
fclose($file);

// 输出文件内容
echo "文件内容:";
echo nl2br($content); // 加上 nl2br 函数将换行符转换为 <br> 标签
} else {
// 文件打开失败
echo "文件打开失败!";
}

十四、PHP 目录操作

简介

在 Web 开发中,我们经常需要对文件夹(目录)进行操作,例如创建新文件夹、复制或移动文件夹、遍历目录等等.PHP 提供了一组内置函数,使得目录操作变得容易而高效.

作用

目录操作可以帮助我们处理文件的组织和管理.它允许我们创建、删除和重命名目录,查找文件和子目录,以及执行其他与目录相关的任务.通过使用 PHP 的目录操作功能,我们可以轻松地处理文件系统中的目录结构.

使用场景

  • 创建项目文件夹和子文件夹
  • 遍历目录并查找特定类型的文件
  • 复制、移动或删除文件夹及其内容
  • 计算文件夹的大小和文件数量
  • 检查目录是否存在,如果不存在则创建

示例

下面是一个示例,展示了如何使用 PHP 进行目录操作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php
// 定义要操作的目录路径
$directoryPath = 'D:\\Software\\phpstudy_pro\\WWW\\localhost\\test';

// 创建目录
if (!is_dir($directoryPath)) { // 如果指定路径不是一个目录
mkdir($directoryPath); // 创建目录
echo "目录创建成功!";
} else {
echo "目录已存在!";
}

// 遍历目录并输出文件名
$dir = opendir($directoryPath); // 打开目录句柄
echo "目录中的文件列表:";
while (($file = readdir($dir)) !== false) { // 读取目录中的文件
if ($file != "." && $file != "..") { // 排除当前目录和上级目录
echo $file . "<br>"; // 输出文件名
}
}
closedir($dir); // 关闭目录句柄

// 复制目录及其内容到新目录
$newDirectoryPath = 'D:\\Software\\phpstudy_pro\\WWW\\localhost\\test_copy';
if (is_dir($directoryPath) && !is_dir($newDirectoryPath)) { // 如果原目录存在且目标目录不存在
mkdir($newDirectoryPath); // 创建目标目录
recurse_copy($directoryPath, $newDirectoryPath); // 调用递归复制函数
echo "目录复制成功!";
} else {
echo "目录复制失败!";
}

// 删除目录及其内容
if (is_dir($directoryPath)) { // 如果目录存在
delete_directory($directoryPath); // 调用递归删除函数
echo "目录删除成功!";
} else {
echo "目录不存在!";
}

// 递归复制目录及其内容
function recurse_copy($src, $dst) {
$dir = opendir($src); // 打开源目录句柄
@mkdir($dst); // 创建目标目录(@符号用于忽略警告)
while (($file = readdir($dir)) !== false) { // 读取源目录中的文件
if ($file != "." && $file != "..") { // 排除当前目录和上级目录
if (is_dir($src . '/' . $file)) { // 如果是子目录
recurse_copy($src . '/' . $file, $dst . '/' . $file); // 递归调用函数复制子目录及其内容
} else {
copy($src . '/' . $file, $dst . '/' . $file); // 复制文件
}
}
}
closedir($dir); // 关闭源目录句柄
}

// 递归删除目录及其内容
function delete_directory($dir) {
if (is_dir($dir)) { // 如果目录存在
$objects = scandir($dir); // 扫描目录,获取文件和子目录列表
foreach ($objects as $object) {
if ($object != "." && $object != "..") { // 排除当前目录和上级目录
if (is_dir($dir . "/" . $object)) { // 如果是子目录
delete_directory($dir . "/" . $object); // 递归调用函数删除子目录及其内容
} else {
unlink($dir . "/" . $object); // 删除文件
}
}
}
rmdir($dir); // 删除目录
}
}