入坑PHP(二)

本文最后更新于:2021年10月3日 晚上

🌈入坑PHP(二)

## 📑包含文件

包含文件的方式(可多次包含)

require

1
2
3
<?php
require '文件目录';
?>

include

1
2
3
<?php
include '文件目录';
?>

包含文件的方式(一次包含)

require_once:
include_once:

区别:

1、require:遇到错误抛出error类别的错误,停止执行
2、include:遇到错误抛出warning类型的错误,继续执行
3、require_once:、include_once:只能包含一次
4、HTML类型的包含页面中存在PHP代码,如果包含到PHP中是可以被执行的
5、包含文件相当于把包含文件中的代码拷贝到主文件中执行,魔术常量除外,魔术常量获取的是所在文件的信息。
6、被包含的文件在主文件被编译时不执行、运行时加载到内存、独立编译包含文件

包含文件的路径

1
2
./		当前目录
../ 上一级目录

这个是没有指定目录直接写文件名,PHP的寻找机制,这些显示寻找顺序从左往右的目录依次查找。

使用来进行包含文件的目录,可以设置多个,路径之间用分豪隔开。

1
2
3
<?php
set_include_path('目录1;目录2;目录3');
?>

关于正反斜杠

正斜(/):web中目录分隔用正斜:https://erhe.group/
反斜(\):物理地址的分隔用反斜,( windows中物理地址正斜和反斜都可以):c:\web\test\

❌PHP错误处理

错误的级别

1、notice:提示
2、warning:警告
3、error:致命错误
notice和warning报错后继续执行,error报错后停止执行

错误的提示方法

方法一:直接显示在浏览器上
方法二:记录在日志中

错误处理的有关配置

在PHP的配置文件中有一个php.ini配置文件

1
2
3
4
1、error_reporting = E_ALL		// 报告所有的错误
2、display_errors = On // 将错误显示在浏览器上
3、log_errors = On // 将错误记录在日志中
4、error_log = '文件路径' // 错误日志保存的位置

在项目开发中有两个模式:

开发模式:错误显示在浏览器上,不要记录在日志中
运行模式:错误不显示在浏览器上,记录是日志中

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$debug=false; // 开发模式
ini_set('error_reporting',E_ALL); // 所有的错误有报告
if($debug){
ini_set('display_errors','on'); // 错误显示是在浏览器上面
ini_set('log_errors','off'); // 错误不显示在日志中
}else{
ini_set('log_errors','off');
ini_set('log_errors','on');
ini_set('error_log','文件路径'); // 错误日志保存的位置
}
?>

PS:ini_set()是用来设置PHP的配置参数。

自定义错误处理

通过trigger_error('')产生一个用户级别的error/warning/notice信息

1
2
3
4
5
6
7
8
9
<?php
$age=100;
if($age>80){
trigger_error('年龄不能超过80岁'); //默认触发了notice级别的错误
trigger_error('年龄不能超过80岁',E_USER_NOTICE); // 触发了notice级别的错误
trigger_error('年龄不能超过80岁',E_USER_WARNING); // 触发了warning级别的错误
trigger_error('年龄不能超过80岁',E_USER_ERROR); // 触发了error级别的错误
}
?>

⭕注意:用户级别的错误的常量名中一定要带有USER

自定义错误处理函数

1
2
3
4
5
6
<?php
function error(){
echo '这是自定义错误处理';
}
set_error_handler('error'); // 注册处理函数,只要有错误就会自动的调用处理函数
?>

还可以带上参数

1
2
3
4
@param $errno int 错误类别
@param $errstr string 错误信息
@param $errfile string 文件地址
@param $errline int 错误行号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
function error($errno,$errstr,$errfile,$errline){
switch($errno){
case E_NOTICE:
case E_USER_NOTICE:
echo '记录在日志中,管理员上班后处理<br>';
break;
case E_WARNING:
case E_USER_WARNING:
echo '给管理员发邮件<br>';
break;
case E_ERROR:
case E_USER_ERROR:
echo '给管理员打电话<br>';
break;
}
echo "错误信息:{$errstr}<br>";
echo "错误信息:{$errfile}<br>";
echo "错误信息:{$errline}<br>";
}
set_error_handler('error'); // 注册处理函数
?>

📂PHP文件编程

文件夹操作

创建文件夹

格式:mkdir('目录/文件夹名,权限,是否递归创建')

普通创建文件夹

1
2
3
<?php
mkdir('目录/文件夹名'); // 目录必须存在
?>

递归创建文件夹

1
2
3
<?php
mkdir('目录/目录/目录/文件夹名',0777,true);
?>

删除文件夹

1
2
3
<?php
rmdir('目录/文件夹名'); // 删除的目录一定为空才能删除
?>

重命名文件夹

1
2
3
<?php
rename('目录/旧文件夹名','目录/新文件夹名');
?>

判断是否是文件夹

1
2
3
<?php
echo is_dir('目录/文件夹名')?'是文件夹':'不是文件夹';
?>

打开和读取遍历文件夹

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
$erhe=opendir('目录/文件夹名'); // 打开文件夹
var_dump($erhe); // 文件夹在PHP中是资源型
echo '<hr>';
echo readdir($erhe),'<br>'; // 读取文件夹,每次只读1个
echo readdir($erhe),'<br>'; // 再次读取文件夹,每次只读1个
echo readdir($erhe),'<br>'; // 再次读取文件夹,每次只读1个
echo '<hr>';
// 若要一次性遍历完文件夹就使用下面的代码
while($f=readdir($erhe)){
echo $f,'<br>';
}
echo '<hr>';
// 若中文有乱码加上编码转换
while($f=readdir($erhe)){
echo iconv('gbk','utf-8',$f),'<br>';
}
echo '<hr>';
// 去掉显示的.与..
while($f=readdir($erhe)){
if($f=='.' || $f=='..')
continue;
echo iconv('gbk','utf-8',$f),'<br>';
}
echo '<hr>';
?>

关闭文件夹

1
closedir($xxx);

📝PHP文件操作

将字符串写入文件

1
2
3
4
<?php
$erhe="床前明月光,\r\n疑是地上霜。";
file_put_contents('目录/文件名',$erhe); // 若文件没有可以自动创建文件,
?>

⭕注意:写入文件的时候是把文件清空重写,在文本中换行是\r\n,带有转义符一定要用双引号!
\r:回车 光标移动到当前行的最前面
\n:换行 将光标下移动一行

文件的读取

将文件读入一个字符串

1
2
3
4
5
<?php
echo file_get_contents('目录/文件名');
echo '<hr>';
readfile('目录/文件名');
?>

打开文件

打开文件并操作

1
2
3
4
5
6
7
<?php
fopen('目录/文件名','模式');
// 模式:
// r:读 read
// w:写 write
// a:追加 append
?>

写入

1
2
3
4
5
<?php
$erhe=fopen('目录/文件名','w'); // 打开文件
fputs($erhe,'写入的内容'."\r\n"); // 写入内容,只写一行
fclose($erhe); // 关闭文件
?>

读取

1
2
3
4
5
6
7
<?php
$erhe=fopen('目录/文件名','r'); // 打开文件
while($f=fgetc($erhe)){ // 读取文件
echo $f,'<br>';
}
fclose($erhe); // 关闭文件
?>

⭕注意:如果只用fgetc($xxx)就只写一行

追加

1
2
3
4
5
<?php
$erhe=fopen('目录/文件名','a'); // 打开文件
fputs($erhe,'追加的内容'); // 追加文件
fclose($erhe); // 关闭文件
?>

⭕注意:打开文件进行操作的时候,如果文件不存在将会报错

判断是否是文件

1
2
3
<?php
echo is_file('目录/文件名')?'是文件':'不是文件';
?>

判断文件或者是文件夹是否存在

1
2
3
<?php
echo file_exists('目录/文件名')?'文件存在':'文件不存在';
?>

删除文件

1
2
3
4
5
6
7
8
9
10
11
<?php
$erhe='./text.txt';
if(file_exists($erhe)){
if(is_dir($erhe))
rmdir($erhe);
elseif(is_file($erhe))
unlink($erhe);
}else {
echo '文件或者是文件夹不存在!';
}
?>

二进制读取

1
2
3
4
5
6
7
<?php
$erhe='目录/文件名';
$fp=fopen($erhe,'r'); // 读取文件
header('content-typpe:文件类别/文件格式'); // 告诉浏览器以那种形式显示
echo fread($fp,fileesize($erhe)); // 二级制读取
// fileesize()用来获取文件大小
?>
1
2
3
4
<?php
header('content-typpe:文件类型/文件后缀名'); // 告诉浏览器以那种形式显示
echo file_get_contents('目录/文件名') // 二级制读取
?>

⭕注意:文本流有明确的结束符,二进制没有明确的结束符,就用过文件大小来判断文件是否读取完毕
echo file_get_contents() 即可用来字符流的读取,也能进行二进制的读取。

✍️表单提交数据的两种方式

两种方式

1、get
2、post

两者区别

原理

get:数据参数一个个的提交
post:数据参数变成整体一次性提交

外观

get:提交数据的时候可以在地址栏上看到提交的参数
post:提交数据的时候地址栏上看不到提交的参数

安全性

get:不安全
post:安全

提交数据的大小

get:提交一般不超过255个字节
post:提交的大小取决于服务器

PS:在php.ini中可以配置post提交的大小

1
post_max_size = 大小

灵活性

get:很灵活,只要有页面的跳转就可以传递参数
post:不灵活,post提交需要有表单的参与

1
2
3
4
5
6
7
8
9
10
11
12
13
14
html跳转
<a href="index.php?name=tom&age=20">这里是跳转</a>

JS跳转
<script>
location.href='index.php?name=tom&age=20';
location.assign='index.php?name=tom&age=20';
location.replace='index.php?name=tom&age=20';
</script>

PHP跳转
<?php
header('location:index.php?name=tom&age=20');
?>

📥服务器接受数据的三种方式

通过名字获取相应的值

1
2
3
$_POST:数组类型,保存的POST提交的值
$_GET:数组类型,保存的GET提交的值
$_REQUEST:数组类型,保存的GET和POST提交的值

不推荐使用$_REQUEST,占用资源较多

关于$_REQUEST

在一个请求中,既有get又有post , get和post传递的数据是一样的,这时候通过$_REQUET获取的数据就要根据配置文件来选择处理保存以及提交数据。

1
request_order = "GP"	# 先获取GET,再获取POST值,后面获取的会将前面获取的值覆盖掉

PS:
1、在开发的时候,如果明确是post提交就使用$_POST获取,如果明确get提交就用$_GET获取
2、request获取效率低,尽可能不要使用,除非提交的类型不确定的情况下才使用。

🤝参数传递

复选框值的传递

复选框命名要注意带’[]’。

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>某人的几大爱好</title>
</head>
<body>
<?php
if(isset($_POST['button'])){
print_r($_POST['hobby']);
}
?>
<from method="post" action="">
某人的几大爱好:
<input type="checkbox" name="hobby[]" value="爬山">爬山
<input type="checkbox" name="hobby[]" value="爬山">抽烟
<input type="checkbox" name="hobby[]" value="爬山">喝酒
<input type="checkbox" name="hobby[]" value="爬山">网吧
<input type="checkbox" name="hobby[]" value="爬山">打牌
<input type="submit" name="button" value="提交">
</from>
</body>
</html>

PS:
1、表单提交到本页面需要判断一下是否有post提交。
2、数组的提交表单元素的名字必须带有’[]’。

实例

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>某人的几大爱好</title>
</head>
<body>
<?php
if(isset($_POST['button'])){
echo '姓名:'.$_POST['username'].'<br>';
echo '密码:'.$_POST['pwd'].'<br>';
echo '性别:'.$_POST['sex'].'<br>';
echo '爱好:',isset($_POST['hobby'])?implode(',',$_POST['hobby']):'没有爱好','<br>';
echo '籍贯:'.$_POST['jiguan'],'<br>';
echo '留言:'.$_POST['words'],'<br>';
}
?>
<from method="post" action="">
姓名:<input type="text" name="username"><br />
密码:<input type="passwd" name="pwd"><br />
性别:<input type="radio" name="sex" value='1' checked>男
<input type="radio" name="sex" value='0'>女<br />
爱好:
<input type="checkbox" name="hobby[]" value="爬山">爬山
<input type="checkbox" name="hobby[]" value="爬山">抽烟
<input type="checkbox" name="hobby[]" value="爬山">喝酒
<input type="checkbox" name="hobby[]" value="爬山">网吧
<input type="checkbox" name="hobby[]" value="爬山">打牌<br />
籍贯:
<select name="jiguan">
<option value="021">上海</option>
<option value="011">广州</option>
</select><br />
留言:
<textarea name="words" cols="30" rows="5"></textarea><br />
<input type="submit" name="button" value="提交">
</from>
</body>
</html>

📝文件上传

开发中需要上传图片、音乐、视频等等,这种上传传递是二进制数据。

客户端上传文件

文件域

1
2
3
<from method="post" action="" enctype='下面三个值'>
<input type="file" name="文件类别">
</from>

表单的enctype属性
默认情况下,表单传递是字符流,不能传递二进制流,通过设置表单的enctype属性传递复合数据。enctype属性的值有
1、application/x-www-form-urlencoded:【默认】,表示传递的是带格式的文本数据
2、multipart/form-data:复合的表单数据(字符串,文件),文件上传必须设置此值
3、text/plain:用于向服务器传递无格式的文本数据,主要用户电子邮件

单词:multipart:复合 form-data:表单数组

服务器接受文件

超全局变量$_FTLES是一个二维数组,用来保存客户端上传到服务器的文件信息。二维数组的行是文件域的名称,列有5个。
1、$_FILES[]['name']:上传的文件名
2、$_FILES[]['type']:上传的类型,这个类型是MIME类型 ( image/jpeg、image/gif、image/png)
3、$_FILES[]['size']:文件的大小,以字节为单位
4、$_FILES[]['tmp_name']:文件上传时的临时文件
5、S_FILES[][ 'error']:错误编码(值有:0、1、2、3、4、6、7)0表示正确

S_FILES[][ 'error']详解

错误描述
0 正确
1 文件大小超过了php.ini中允许的最大值upload_max_filesize = 2M
2 文件大小超过了表单允许的最大值
3 文件大小超过了表单允许的最大值
4 没有文件上传
6 找不到临时文件
7 文件写入失败

⭕注意:MAX_FILE_SIZE必须在文件域的上面

将文件移动到指定位置

函数

1
move_uploaded_file('临时地址','目标地址');

实例代码

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传</title>
</head>
<body>
<?php
if(!empty($_POST)){
if($_FILES['face']['error']==0){ // 上传正确
// 文件上传
move_uploaded_file($_FILES['face']['tmp_name'],'./'.$_FILES['face']['name']);
}else {
echo '上传错误';
echo '错误代码:'.$_FILES['face']['error'];
}
}
?>
<from method="post" action="" enctype='multipart/form-data'>
<input type="file" name="face">
<input type="submit" name="button" value="上传">
</from>
</body>
</html>

⭕注意:上传的同名文件会被覆盖

与文件上传的有关配置

post_max_size = 8M:表单允许的最大值
upload_max_filesize = 2M:允许上传的文件大小
upload_tmp dir =F:lwampltmp:指定临时文件地址,如果不知道操作系统指定
file_uploads = On:是否允许文件上传
max_file_uploads = 20∶允许同时上传20个文件

优化文件上传

更改文件名

通过时间戳做文件名
1
2
3
4
5
6
<?php
$erhe='XXX.XXX.jpg';
// echo strrchr($erhe,'.'); // 从最后一个点开始截取。一直截到最后
// rand(100,999) // 生成100-999之间的随机数
echo time().rand(100,999).strrchr($erhe,'.');
?>
通过uniqod()做文件名
1
2
3
4
5
6
<?php
$erhe='face.stu.jpg';
echo uniqid().strrchr($erhe,'.'),'<br>'; // 生成唯一的ID
echo uniqid('XXXX').strrchr($erhe,'.'),'<br>'; // 带有前缀
echo uniqid('XXXX',true).strrchr($erhe,'.'),'<br>'; // 唯一ID+随机数
?>

验证文件格式

方法一:判断文件的扩展名(不能识别文件伪装)
操作思路:将文件的后缀和允许的后缀对比

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传</title>
</head>
<body>
<?php
if(!empty($_POST)){
$allow=array('.jpg','.png','.gif'); // 允许的扩展名
$ext=strrchr($_FILES['face']['name'],'.'); // 上传文件扩展名
if(in_array($ext,$allow))
echo '允许上传';
else {
echo '文件不合法!';
}
}
?>
<from method="post" action="" enctype='multipart/form-data'>
<input type="file" name="face">
<input type="submit" name="button" value="上传">
</from>
</body>
</html>

⭕注意:比较扩展名不能防止文件伪装

方法二:判断mime类型

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传</title>
</head>
<body>
<?php
if(!empty($_POST)){
$allow=array('image/jpge','image/png','image/gif'); // 允许的扩展名
$mime=$_FILES['face']['type']; // 上传文件扩展名
if(in_array($mime,$allow))
echo '允许上传';
else {
echo '文件不合法!';
}
}
?>
<from method="post" action="" enctype='multipart/form-data'>
<input type="file" name="face">
<input type="submit" name="button" value="上传">
</from>
</body>
</html>

⭕注意:判断mime不能防止文件伪装

方法三、php_fileinfo扩展(可以防止文件伪装)
在php.ini中开启fileinfo扩展

1
extension=php_fileinfo.dll

⭕注意:开启fileinfo扩展以后,就可以使用finfo_*的函数了

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传</title>
</head>
<body>
<?php
if(!empty($_POST)){
// 第一步:创建finfo资源
$info=finfo_open(FILEINFO_MIME_TYPE);
// 第二步:将finfo资源和文件进行比较
$mime=finfo_file($info,$_FILES['face']['tmpp_name']);
// 第三步:比较是否合法
$allow=array('image/jpge','image/png','image/gif');
echo in_array($mime,$allow)?'合法':'不合法';
}
?>
<from method="post" action="" enctype='multipart/form-data'>
<input type="file" name="face">
<input type="submit" name="button" value="上传">
</from>
</body>
</html>

实例

步骤:

  • 第一步:验证是否有误
  • 第二步:验证格式
  • 第三步:验证大小
  • 第四步:验证是否是http上传
  • 第五步:上传实现

代码实现

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传</title>
</head>
<body>
<?php
function check($file){
// 1、验证文件是否有误
if ($file['error'] != 0) {
switch ($file['error']) {
case 1:
return '文件大小超过了php.ini中允许的最大值:' . ini_get('upload_max_filesize');
case 2:
return '文件大小超过了表单允许的最大值';
case 3:
return '文件大小超过了表单允许的最大值';
case 4:
return '没有文件上传';
case 6:
return '找不到临时文件';
case 7:
return '文件写入失败';
default:
return '未知错误';
}
}
// 2、验证格式
$info = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($info, $file['tmp_name']);
$allow = array('image/jpeg', 'image/png', 'image/gif'); // 允许的文件类别
if (!in_array($mime, $allow)) {
return '只能上传' . implode(',', $allow) . '格式';
}
// 3、验证大小
$size = 123456789;
if ($file['size'] > $size) {
return '文件大小不能超过' . number_format($size / 1024, 1) . 'k';
}
// 4、验证是否是http上传
if (!is_uploaded_file($file['tmp_name']))
return '文件不是HTTP POST上传的 <br>';
return null; // 没有错误
}
// 表单提交
if (!empty($_POST)){
// 上传文件过程中有错误显示错误
if ($error=check($_FILES['face'])){
echo $error;
}else{
// 文件上传,上传的文件保存到当前的文件夹中
$foldername=date('Y-m-d'); // 文件夹的名称
$folderpath="./uploads/{$foldername}"; // 文件夹的路径
if(!is_dir($folderpath))
mkdir($folderpath);
$filename=uniqid('',true).strrchr($_FILES['face']['name'],'.'); // 文件名
$filepath="$folderpath/$filename"; // 文件路径
if (move_uploaded_file($_FILES['face']['tmp_name'],$filepath))
echo "上传成功,路径是:{$foldername}/{$fliename}";
else
echo '上传失败<br>';
}
}
?>
<from method="post" action="" enctype='multipart/form-data'>
<input type="file" name="face">
<input type="submit" name="button" value="上传">
</from>
</body>
</html>

小结:

1、将时间戳转换格式

1
2
echo date('Y-m-d H:i:s',1231346),'<br>';	// 将时间戳转换成年-月-日 小时:分钟:秒
echo date('Y-m-d H:i:s'),'<br>'; // 将时间戳转换成年-月-日 小时:分钟:秒

2、设置时区(更改php.ini)

1
date.timezone = PRC	// PRC:中华人民共和国

3、PHP的执行可以不需要Apache的参与

📣特别声明

此文章全部都是依靠自己的学习理解来写的原创文章,难免可能会出现有错误的地方,

如果大家以后阅读的时候发现有问题,那就麻烦到下方评论区来进行错误指出,使错误尽快做出改正,

在此,感谢大家的阅读与支持!🤝💦🎉

🍻支持一下

觉得我写的好的话可以支持一下我哦~持续关注我,会更新其他好玩且实用的项目。

👋如果我能帮助到你,那就请我喝杯🧋呗~👇👇👇


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!