PHP后端开发学习笔记
第一章 PHP概述与环境搭建
1.1 前后端交互概述
Web服务器的作用
Web服务器的主要功能:
- 接收客户端(PC/Pad/Phone)的请求
- 查找需要的数据(文件/数据库/其它系统)
- 发送响应回客户端
Web服务器分类
| 类型 |
说明 |
示例 |
| 静态Web服务器 |
提供的内容任何人任何时间访问都是相同的 |
Nginx、Apache(静态资源) |
| 动态Web服务器 |
提供的内容会根据用户身份、时间、条件等发生变化 |
PHP、JSP、ASP.NET |
前后端交互流程
┌─────────────┐ HTTP请求 ┌─────────────┐ SQL查询 ┌─────────────┐
│ 客户端 │ ─────────────> │ Web服务器 │ ─────────────> │ 数据库 │
│ (浏览器) │ │ (PHP) │ │ (MySQL) │
└─────────────┘ <───────────── └─────────────┘ <───────────── └─────────────┘
HTTP响应 数据结果
1.2 PHP简介
什么是PHP
PHP(Hypertext Preprocessor)是一种通用开源脚本语言,特别适合Web开发。
PHP特点:
- 开源免费
- 跨平台(Windows/Linux/macOS)
- 支持多种数据库
- 面向对象
- 简单易学
PHP运行环境
LNMP架构:
- Linux:操作系统
- Nginx:Web服务器
- MySQL:数据库
- PHP:脚本语言
Nginx搭建PHP动态网站配置示例:
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
第二章 PHP基础语法
2.1 PHP标记与注释
PHP标记
<?php
// 标准标记(推荐使用)
echo "Hello World";
?>
<?php
// 短标记(需要配置short_open_tag = On)
echo "Hello World";
?>
<?= "Hello World" ?> <!-- 短输出标记,等同于 <?php echo "Hello World"; ?> -->
注释
<?php
// 单行注释
# 单行注释(较少使用)
/*
* 多行注释
* 可以跨越多行
*/
?>
2.2 变量
变量定义
PHP变量以 $ 符号开头,后跟变量名。
<?php
$name = "张三"; // 字符串
$age = 25; // 整数
$price = 99.9; // 浮点数
$is_active = true; // 布尔值
?>
变量命名规则
| 规则 |
说明 |
示例 |
| 必须以$开头 |
变量名必须以美元符号开始 |
$name |
| 首字符 |
必须是字母或下划线 |
$_name, $name |
| 后续字符 |
可以是字母、数字、下划线 |
$name_1 |
| 区分大小写 |
变量名区分大小写 |
$Name 和 $name 是不同的变量 |
| 不能使用保留字 |
不能使用PHP保留关键字 |
不能用 $class, $function |
可变变量
<?php
$a = "hello";
$$a = "world"; // 等同于 $hello = "world"
echo $a; // 输出: hello
echo $$a; // 输出: world
echo $hello; // 输出: world
?>
2.3 常量
define() 定义常量
<?php
define("PI", 3.14159);
define("SITE_NAME", "我的网站", true); // 第三个参数true表示不区分大小写
echo PI; // 输出: 3.14159
echo SITE_NAME; // 输出: 我的网站
?>
const 定义常量
<?php
const MAX_SIZE = 100;
const DB_HOST = "localhost";
echo MAX_SIZE; // 输出: 100
?>
预定义常量
<?php
echo PHP_VERSION; // PHP版本
echo PHP_OS; // 操作系统
echo PHP_INT_MAX; // 整数最大值
echo __FILE__; // 当前文件路径
echo __LINE__; // 当前行号
echo __DIR__; // 当前目录
?>
2.4 数据类型
基本数据类型
| 类型 |
说明 |
示例 |
| int |
整数 |
$num = 100; |
| float |
浮点数 |
$price = 99.9; |
| bool |
布尔值 |
$flag = true; |
| string |
字符串 |
$name = "张三"; |
| null |
空值 |
$var = null; |
复合数据类型
| 类型 |
说明 |
示例 |
| array |
数组 |
$arr = [1, 2, 3]; |
| object |
对象 |
$obj = new Person(); |
特殊类型
| 类型 |
说明 |
示例 |
| resource |
资源 |
文件句柄、数据库连接 |
| NULL |
空值 |
未赋值或赋值为null |
类型检测
<?php
$var = 100;
var_dump($var); // 输出类型和值
echo gettype($var); // 输出: integer
// 类型判断函数
is_int($var); // 是否为整数
is_float($var); // 是否为浮点数
is_bool($var); // 是否为布尔值
is_string($var); // 是否为字符串
is_array($var); // 是否为数组
is_null($var); // 是否为null
?>
类型转换
<?php
// 自动类型转换
$a = "100";
$b = $a + 1; // 字符串自动转为整数
echo $b; // 输出: 101
// 强制类型转换
$str = "100.9abc";
$int = (int)$str; // 强制转为整数: 100
$float = (float)$str; // 强制转为浮点: 100.9
// 类型转换函数
$num = intval("100"); // 转为整数
$float = floatval("100.9"); // 转为浮点
$str = strval(100); // 转为字符串
?>
2.5 单引号与双引号
区别对比
| 特性 |
单引号 |
双引号 |
| 变量解析 |
不解析 |
解析 |
| 转义字符 |
仅支持 \' 和 \\ |
支持所有转义字符 |
| 执行速度 |
较快 |
较慢 |
| 使用场景 |
纯字符串 |
包含变量或转义字符 |
代码示例
<?php
$name = "张三";
// 单引号 - 不解析变量
echo 'Hello $name'; // 输出: Hello $name
// 双引号 - 解析变量
echo "Hello $name"; // 输出: Hello 张三
echo "Hello {$name}"; // 输出: Hello 张三(推荐写法)
// 转义字符
echo 'Hello\nWorld'; // 输出: Hello\nWorld
echo "Hello\nWorld"; // 输出: Hello(换行)World
?>
2.6 响应头定制
<?php
// 设置响应头
header("Content-Type: text/html; charset=utf-8");
header("Access-Control-Allow-Origin: *");
// 重定向
header("Location: https://www.example.com");
// 设置HTTP状态码
header("HTTP/1.1 404 Not Found");
?>
第三章 PHP运算符
3.1 算术运算符
<?php
$a = 10;
$b = 3;
echo $a + $b; // 加法: 13
echo $a - $b; // 减法: 7
echo $a * $b; // 乘法: 30
echo $a / $b; // 除法: 3.333...
echo $a % $b; // 取模: 1
echo $a ** $b; // 幂运算: 1000
?>
3.2 自增自减运算符
<?php
$a = 10;
// 前置自增:先加1,再使用
echo ++$a; // 输出: 11,$a变为11
// 后置自增:先使用,再加1
$b = 10;
echo $b++; // 输出: 10,$b变为11
echo $b; // 输出: 11
// 前置自减
echo --$a; // 输出: 10
// 后置自减
echo $a--; // 输出: 10,$a变为9
?>
3.3 比较运算符
| 运算符 |
说明 |
示例 |
== |
等于(值相等) |
10 == "10" → true |
=== |
全等(值和类型都相等) |
10 === "10" → false |
!= |
不等于 |
10 != 20 → true |
<> |
不等于 |
10 <> 20 → true |
!== |
不全等 |
10 !== "10" → true |
> |
大于 |
10 > 5 → true |
< |
小于 |
5 < 10 → true |
>= |
大于等于 |
10 >= 10 → true |
<=> |
太空船运算符 |
1 <=> 2 → -1 |
<?php
// == 与 === 的区别
var_dump(10 == "10"); // true(弱类型比较)
var_dump(10 === "10"); // false(强类型比较)
// 太空船运算符(PHP 7+)
echo 1 <=> 2; // -1(左边小于右边)
echo 2 <=> 2; // 0(相等)
echo 3 <=> 2; // 1(左边大于右边)
?>
3.4 赋值运算符
<?php
$a = 10;
$a += 5; // 等同于 $a = $a + 5
$a -= 5; // 等同于 $a = $a - 5
$a *= 5; // 等同于 $a = $a * 5
$a /= 5; // 等同于 $a = $a / 5
$a %= 5; // 等同于 $a = $a % 5
$a .= "abc"; // 等同于 $a = $a . "abc"(字符串连接)
?>
3.5 逻辑运算符
| 运算符 |
说明 |
示例 |
&& |
与(并且) |
$a && $b |
| ` |
|
` |
! |
非(取反) |
!$a |
and |
与(优先级低) |
$a and $b |
or |
或(优先级低) |
$a or $b |
xor |
异或 |
$a xor $b |
<?php
$a = true;
$b = false;
var_dump($a && $b); // false
var_dump($a || $b); // true
var_dump(!$a); // false
var_dump($a xor $b); // true(一个为真,另一个为假)
?>
3.6 三元运算符
<?php
$age = 20;
// 基本语法:条件 ? 真值 : 假值
$status = $age >= 18 ? "成年" : "未成年";
echo $status; // 输出: 成年
// 三元运算符简写(PHP 5.3+)
$name = $username ?: "游客"; // 如果$username为真则使用它,否则使用"游客"
?>
第四章 PHP流程控制
4.1 条件判断
if 语句
<?php
$score = 85;
if ($score >= 90) {
echo "优秀";
} elseif ($score >= 80) {
echo "良好";
} elseif ($score >= 60) {
echo "及格";
} else {
echo "不及格";
}
?>
switch 语句
<?php
$day = 3;
switch ($day) {
case 1:
echo "星期一";
break;
case 2:
echo "星期二";
break;
case 3:
echo "星期三";
break;
default:
echo "其他";
}
?>
4.2 循环结构
while 循环
<?php
$i = 1;
while ($i <= 10) {
echo $i . " ";
$i++;
}
// 输出: 1 2 3 4 5 6 7 8 9 10
?>
do-while 循环
<?php
$i = 1;
do {
echo $i . " ";
$i++;
} while ($i <= 10);
// 至少执行一次
?>
for 循环
<?php
for ($i = 1; $i <= 10; $i++) {
echo $i . " ";
}
?>
foreach 循环
<?php
// 遍历索引数组
$arr = ["苹果", "香蕉", "橙子"];
foreach ($arr as $value) {
echo $value . " ";
}
// 遍历关联数组
$user = ["name" => "张三", "age" => 25, "city" => "北京"];
foreach ($user as $key => $value) {
echo "$key: $value\n";
}
?>
4.3 循环控制
break 语句
<?php
for ($i = 1; $i <= 10; $i++) {
if ($i == 5) {
break; // 跳出整个循环
}
echo $i . " ";
}
// 输出: 1 2 3 4
?>
continue 语句
<?php
for ($i = 1; $i <= 10; $i++) {
if ($i == 5) {
continue; // 跳过本次循环,继续下一次
}
echo $i . " ";
}
// 输出: 1 2 3 4 6 7 8 9 10
?>
exit/die 语句
<?php
for ($i = 1; $i <= 10; $i++) {
if ($i == 5) {
exit("程序结束"); // 终止整个程序
}
echo $i . " ";
}
// 输出: 1 2 3 4 程序结束
?>
第五章 PHP函数
5.1 函数定义
<?php
// 基本函数
function sayHello() {
echo "Hello World!";
}
sayHello(); // 调用函数
// 带参数的函数
function greet($name) {
echo "Hello, $name!";
}
greet("张三"); // 输出: Hello, 张三!
// 带默认参数的函数
function greet2($name = "游客") {
echo "Hello, $name!";
}
greet2(); // 输出: Hello, 游客!
greet2("李四"); // 输出: Hello, 李四!
?>
5.2 返回值
<?php
function add($a, $b) {
return $a + $b;
}
$result = add(10, 20);
echo $result; // 输出: 30
// 返回多个值(使用数组)
function getMinMax($arr) {
return [min($arr), max($arr)];
}
[$min, $max] = getMinMax([1, 5, 3, 9, 2]);
echo "最小值: $min, 最大值: $max";
?>
5.3 参数类型
<?php
// 类型声明(PHP 7+)
function add(int $a, int $b): int {
return $a + $b;
}
// 可变参数
function sum(...$numbers) {
return array_sum($numbers);
}
echo sum(1, 2, 3, 4, 5); // 输出: 15
// 引用传递
function increment(&$num) {
$num++;
}
$value = 10;
increment($value);
echo $value; // 输出: 11
?>
5.4 文件包含函数
<?php
// include:包含文件,失败时警告,继续执行
include "header.php";
// include_once:只包含一次,避免重复包含
include_once "config.php";
// require:包含文件,失败时致命错误,停止执行
require "database.php";
// require_once:只包含一次
require_once "functions.php";
?>
include vs require 对比:
| 特性 |
include |
require |
| 失败行为 |
警告,继续执行 |
致命错误,停止执行 |
| 使用场景 |
可选文件 |
必需文件 |
第六章 PHP常用函数库
6.1 数学函数
<?php
// 基本数学运算
echo abs(-10); // 绝对值: 10
echo round(3.6); // 四舍五入: 4
echo ceil(3.1); // 向上取整: 4
echo floor(3.9); // 向下取整: 3
// 幂运算和开方
echo pow(2, 3); // 2的3次方: 8
echo sqrt(16); // 平方根: 4
// 随机数
echo rand(); // 随机整数
echo rand(1, 100); // 1-100之间的随机整数
echo mt_rand(1, 100); // 更好的随机数算法
// 最大最小值
echo max(1, 5, 3, 9); // 最大值: 9
echo min(1, 5, 3, 9); // 最小值: 1
// 三角函数
echo sin(0); // 正弦: 0
echo cos(0); // 余弦: 1
?>
6.2 字符串函数
<?php
$str = "Hello World";
// 字符串长度
echo strlen($str); // 长度: 11
echo mb_strlen("你好世界"); // 多字节字符串长度: 4
// 字符串查找
echo strpos($str, "World"); // 查找位置: 6
echo strrpos($str, "o"); // 最后出现位置: 7
// 字符串截取
echo substr($str, 0, 5); // 截取: Hello
echo substr($str, -5); // 从后面截取: World
// 字符串替换
echo str_replace("World", "PHP", $str); // 替换: Hello PHP
// 大小写转换
echo strtoupper($str); // 大写: HELLO WORLD
echo strtolower($str); // 小写: hello world
echo ucfirst("hello"); // 首字母大写: Hello
echo ucwords("hello world"); // 每个单词首字母大写: Hello World
// 去除空白
$str2 = " Hello ";
echo trim($str2); // 去除两端空白
echo ltrim($str2); // 去除左侧空白
echo rtrim($str2); // 去除右侧空白
// 字符串分割
$arr = explode(" ", $str); // 分割为数组
print_r($arr); // ["Hello", "World"]
// 数组连接
echo implode("-", $arr); // 连接为字符串: Hello-World
// 字符串重复
echo str_repeat("AB", 3); // 重复: ABABAB
// 字符串反转
echo strrev($str); // 反转: dlroW olleH
// MD5加密
echo md5("password"); // MD5哈希值
?>
6.3 时间日期函数
<?php
// 获取当前时间
echo time(); // Unix时间戳
// 格式化日期
echo date("Y-m-d H:i:s"); // 2024-01-15 10:30:00
echo date("Y年m月d日"); // 2024年01月15日
// 常用格式符
// Y: 4位年份 m: 2位月份 d: 2位日期
// H: 24小时制 i: 分钟 s: 秒
// w: 星期几(0-6) W: 第几周
// 时间戳转日期
echo date("Y-m-d", 1705305600);
// 日期转时间戳
echo strtotime("2024-01-15");
echo strtotime("+1 day"); // 明天此时
echo strtotime("+1 week"); // 一周后
// 获取详细信息
$date = getdate();
print_r($date);
// 包含: year, month, mday, hours, minutes, seconds 等
// 检查日期有效性
var_dump(checkdate(2, 29, 2024)); // 检查2024年2月29日是否有效
?>
第七章 PHP数组操作
7.1 数组创建
<?php
// 索引数组
$arr1 = [1, 2, 3, 4, 5];
$arr2 = array("苹果", "香蕉", "橙子");
// 关联数组
$user = [
"name" => "张三",
"age" => 25,
"city" => "北京"
];
// 多维数组
$users = [
["name" => "张三", "age" => 25],
["name" => "李四", "age" => 30]
];
?>
7.2 数组操作
<?php
$arr = ["a", "b", "c", "d"];
// 访问元素
echo $arr[0]; // 输出: a
// 添加元素
$arr[] = "e"; // 末尾添加
array_push($arr, "f"); // 末尾添加
array_unshift($arr, "z"); // 开头添加
// 删除元素
array_pop($arr); // 删除末尾元素
array_shift($arr); // 删除开头元素
unset($arr[2]); // 删除指定索引
// 数组长度
echo count($arr);
// 检查元素是否存在
var_dump(in_array("a", $arr));
var_dump(array_key_exists(0, $arr));
// 查找元素位置
echo array_search("b", $arr);
// 数组合并
$arr1 = [1, 2];
$arr2 = [3, 4];
$merged = array_merge($arr1, $arr2);
// 数组切片
$sliced = array_slice($arr, 1, 2);
// 数组排序
sort($arr); // 升序排序
rsort($arr); // 降序排序
asort($arr); // 按值升序(保持键值关系)
ksort($arr); // 按键升序
?>
7.3 数组遍历
<?php
$user = ["name" => "张三", "age" => 25, "city" => "北京"];
// foreach遍历
foreach ($user as $key => $value) {
echo "$key: $value\n";
}
// 获取所有键
$keys = array_keys($user);
// 获取所有值
$values = array_values($user);
// 判断是否为数组
var_dump(is_array($user));
// 数组转字符串
echo implode(", ", $user);
?>
第八章 PHP文件操作
8.1 file_get_contents
<?php
// 读取整个文件
$content = file_get_contents("data.txt");
echo $content;
// 读取远程文件
$html = file_get_contents("https://www.example.com");
// 写入文件
file_put_contents("output.txt", "Hello World");
// 追加写入
file_put_contents("output.txt", "\n新内容", FILE_APPEND);
?>
8.2 fopen 文件操作
<?php
// 打开文件
// 模式: r(只读), w(写入,清空), a(追加), x(创建写入)
$file = fopen("data.txt", "r");
// 读取一行
echo fgets($file);
// 读取一个字符
echo fgetc($file);
// 读取指定长度
echo fread($file, 1024);
// 检查文件结束
while (!feof($file)) {
echo fgets($file);
}
// 写入文件
$file = fopen("output.txt", "w");
fwrite($file, "Hello World\n");
fwrite($file, "第二行内容");
// 关闭文件
fclose($file);
?>
8.3 目录操作
<?php
// 创建目录
mkdir("new_folder", 0777, true); // true表示递归创建
// 删除目录(必须为空)
rmdir("empty_folder");
// 检查是否为目录
var_dump(is_dir("folder"));
// 打开目录
$dir = opendir("folder");
while ($file = readdir($dir)) {
echo $file . "\n";
}
closedir($dir);
// 更简单的方式:scandir
$files = scandir("folder");
print_r($files);
// 获取当前目录
echo getcwd();
// 切换目录
chdir("new_folder");
?>
8.4 文件操作补充
<?php
// 检查文件是否存在
var_dump(file_exists("data.txt"));
// 检查是否为文件
var_dump(is_file("data.txt"));
// 获取文件信息
echo filesize("data.txt"); // 文件大小
echo filemtime("data.txt"); // 修改时间
echo fileatime("data.txt"); // 访问时间
// 复制文件
copy("source.txt", "dest.txt");
// 移动/重命名文件
rename("old.txt", "new.txt");
// 删除文件
unlink("delete.txt");
// 获取文件扩展名
echo pathinfo("file.txt", PATHINFO_EXTENSION);
// 获取文件名
echo basename("/path/to/file.txt");
?>
8.5 临时文件操作
<?php
// 创建临时文件
$temp = tmpfile();
fwrite($temp, "临时数据");
// 读取临时文件
rewind($temp);
echo fread($temp, 1024);
// 关闭后自动删除
fclose($temp);
// 创建临时文件名
$tempname = tempnam(sys_get_temp_dir(), "prefix_");
file_put_contents($tempname, "临时数据");
unlink($tempname); // 手动删除
?>
第九章 PHP文件上传
9.1 配置说明
php.ini 相关配置:
| 配置项 |
说明 |
默认值 |
| file_uploads |
是否允许文件上传 |
On |
| upload_max_filesize |
上传文件最大大小 |
2M |
| post_max_size |
POST数据最大大小 |
8M |
| upload_tmp_dir |
临时文件目录 |
系统默认 |
| max_file_uploads |
同时上传文件最大数量 |
20 |
9.2 $_FILES 数组
<?php
// $_FILES 数组结构
/*
$_FILES['file']['name'] - 文件原名
$_FILES['file']['type'] - 文件MIME类型
$_FILES['file']['tmp_name'] - 临时文件路径
$_FILES['file']['error'] - 错误码
$_FILES['file']['size'] - 文件大小(字节)
*/
// 错误码说明
/*
UPLOAD_ERR_OK (0) - 没有错误
UPLOAD_ERR_INI_SIZE (1) - 超过php.ini中upload_max_filesize
UPLOAD_ERR_FORM_SIZE (2) - 超过HTML表单中MAX_FILE_SIZE
UPLOAD_ERR_PARTIAL (3) - 文件只有部分被上传
UPLOAD_ERR_NO_FILE (4) - 没有文件被上传
UPLOAD_ERR_NO_TMP_DIR (6) - 找不到临时文件夹
UPLOAD_ERR_CANT_WRITE (7) - 文件写入失败
*/
?>
9.3 文件上传示例
HTML表单:
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<button type="submit">上传</button>
</form>
PHP处理:
<?php
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
$tmp_name = $_FILES['file']['tmp_name'];
$name = $_FILES['file']['name'];
// 移动上传文件
if (move_uploaded_file($tmp_name, "uploads/" . $name)) {
echo "文件上传成功";
} else {
echo "文件上传失败";
}
}
?>
9.4 文件上传安全
<?php
// 文件类型限制
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($_FILES['file']['type'], $allowed_types)) {
die("不支持的文件类型");
}
// 文件扩展名限制
$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$allowed_exts = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array(strtolower($ext), $allowed_exts)) {
die("不支持的文件扩展名");
}
// 文件大小限制
$max_size = 2 * 1024 * 1024; // 2MB
if ($_FILES['file']['size'] > $max_size) {
die("文件过大");
}
// 重命名文件(防止覆盖和中文乱码)
$new_name = uniqid() . '.' . $ext;
move_uploaded_file($tmp_name, "uploads/" . $new_name);
?>
第十章 PHP命令执行与安全
10.1 命令执行函数
<?php
// system - 执行命令并输出结果
system("ls -la");
// exec - 执行命令,返回最后一行
$output = [];
exec("ls -la", $output);
print_r($output);
// passthru - 执行命令并输出原始结果
passthru("ls -la");
// shell_exec - 执行命令返回完整输出
$output = shell_exec("ls -la");
echo $output;
// 反引号 - 同shell_exec
$output = `ls -la`;
echo $output;
// proc_open - 更复杂的进程控制
$descriptors = [
0 => ["pipe", "r"], // stdin
1 => ["pipe", "w"], // stdout
2 => ["pipe", "w"] // stderr
];
$process = proc_open("ls -la", $descriptors, $pipes);
// popen - 打开进程管道
$handle = popen("ls -la", "r");
echo fread($handle, 4096);
pclose($handle);
?>
10.2 安全注意事项
<?php
// 危险:直接使用用户输入
$cmd = $_GET['cmd'];
system($cmd); // 极其危险!
// 安全:使用escapeshellarg转义参数
$file = escapeshellarg($_GET['file']);
system("cat " . $file);
// 安全:使用escapeshellcmd转义整个命令
$cmd = escapeshellcmd($_GET['cmd']);
system($cmd);
// 更安全:使用白名单限制命令
$allowed = ['ls', 'pwd', 'whoami'];
$cmd = $_GET['cmd'];
if (in_array($cmd, $allowed)) {
system($cmd);
}
?>
第十一章 PHP错误处理与日志
11.1 错误类型
| 错误级别 |
常量 |
说明 |
| E_ERROR |
1 |
致命运行时错误 |
| E_WARNING |
2 |
运行时警告 |
| E_PARSE |
4 |
编译时语法错误 |
| E_NOTICE |
8 |
运行时提示 |
| E_ALL |
~0 |
所有错误 |
11.2 错误报告设置
<?php
// 显示所有错误
error_reporting(E_ALL);
ini_set('display_errors', 1);
// 隐藏所有错误
error_reporting(0);
ini_set('display_errors', 0);
// 只显示错误和警告
error_reporting(E_ERROR | E_WARNING);
?>
11.3 错误处理函数
<?php
// 自定义错误处理
function handleError($errno, $errstr, $errfile, $errline) {
echo "错误 [$errno]: $errstr\n";
echo "文件: $errfile\n";
echo "行号: $errline\n";
return true;
}
set_error_handler("handleError");
// 触发错误
trigger_error("自定义错误信息", E_USER_WARNING);
// 异常处理
try {
throw new Exception("发生异常");
} catch (Exception $e) {
echo "异常: " . $e->getMessage();
}
// 自定义异常处理
function handleException($exception) {
echo "未捕获异常: " . $exception->getMessage();
}
set_exception_handler("handleException");
?>
11.4 日志记录
<?php
// 配置日志
ini_set('log_errors', 1);
ini_set('error_log', '/var/log/php_errors.log');
// 手动记录日志
error_log("这是一条日志信息");
error_log("发送邮件", 1, "admin@example.com");
// 使用syslog
openlog("myapp", LOG_PID | LOG_PERROR, LOG_LOCAL0);
syslog(LOG_INFO, "用户登录成功");
closelog();
?>
第十二章 PHP正则表达式
12.1 正则函数
<?php
// preg_match - 匹配一次
$pattern = '/\d+/';
$str = "abc123def";
if (preg_match($pattern, $str, $matches)) {
print_r($matches); // ['123']
}
// preg_match_all - 匹配所有
preg_match_all('/\d+/', "a1b22c333", $matches);
print_r($matches); // [['1', '22', '333']]
// preg_replace - 替换
$result = preg_replace('/\d+/', '*', "a1b22c333");
echo $result; // a*b*c*
// preg_split - 分割
$arr = preg_split('/\s+/', "a b c");
print_r($arr); // ['a', 'b', 'c']
// preg_grep - 过滤数组
$arr = ['abc', '123', 'def', '456'];
$result = preg_grep('/^\d+$/', $arr);
print_r($result); // ['123', '456']
?>
12.2 常用正则模式
<?php
// 邮箱验证
$email_pattern = '/^[\w\-\.]+@[\w\-]+\.[a-z]{2,}$/i';
// 手机号验证(中国)
$phone_pattern = '/^1[3-9]\d{9}$/';
// 身份证号
$id_pattern = '/^\d{17}[\dXx]$/';
// URL验证
$url_pattern = '/^https?:\/\/[\w\-]+(\.[\w\-]+)+.*$/';
// IP地址
$ip_pattern = '/^\d{1,3}(\.\d{1,3}){3}$/';
// 日期格式 YYYY-MM-DD
$date_pattern = '/^\d{4}-\d{2}-\d{2}$/';
?>
12.3 正则修饰符
| 修饰符 |
说明 |
| i |
不区分大小写 |
| m |
多行模式 |
| s |
单行模式(.匹配换行) |
| u |
UTF-8模式 |
| g |
全局匹配(preg_match_all默认) |
第十三章 PHP面向对象编程
13.1 类与对象
<?php
class Person {
// 属性
public $name;
public $age;
private $secret;
// 构造函数
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
// 方法
public function sayHello() {
return "Hello, I'm " . $this->name;
}
// 静态方法
public static function getDescription() {
return "This is a Person class";
}
}
// 创建对象
$person = new Person("张三", 25);
echo $person->sayHello();
echo Person::getDescription();
?>
13.2 访问修饰符
| 修饰符 |
本类 |
子类 |
外部 |
| public |
✓ |
✓ |
✓ |
| protected |
✓ |
✓ |
✗ |
| private |
✓ |
✗ |
✗ |
<?php
class Demo {
public $public = "public";
protected $protected = "protected";
private $private = "private";
public function showAll() {
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
?>
13.3 继承
<?php
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function speak() {
return "Some sound";
}
}
class Dog extends Animal {
public function speak() {
return "Woof!";
}
public function fetch() {
return $this->name . " is fetching";
}
}
$dog = new Dog("Buddy");
echo $dog->speak(); // Woof!
echo $dog->fetch(); // Buddy is fetching
?>
13.4 魔术方法
<?php
class MagicClass {
private $data = [];
// 构造函数
public function __construct() {
echo "对象创建\n";
}
// 析构函数
public function __destruct() {
echo "对象销毁\n";
}
// 获取不存在属性时调用
public function __get($name) {
return $this->data[$name] ?? null;
}
// 设置不存在属性时调用
public function __set($name, $value) {
$this->data[$name] = $value;
}
// 调用不存在方法时调用
public function __call($name, $arguments) {
echo "调用方法: $name\n";
}
// 对象转字符串时调用
public function __toString() {
return "MagicClass object";
}
// 克隆时调用
public function __clone() {
echo "对象被克隆\n";
}
}
?>
第十四章 PHP序列化与反序列化
14.1 基本概念
序列化:将对象或数据转换为可存储/传输的字符串格式。
反序列化:将字符串还原为原来的对象或数据。
14.2 序列化操作
<?php
// 序列化数组
$arr = ['name' => '张三', 'age' => 25];
$serialized = serialize($arr);
echo $serialized;
// 输出: a:2:{s:4:"name";s:6:"张三";s:3:"age";i:25;}
// 反序列化
$unserialized = unserialize($serialized);
print_r($unserialized);
// 序列化对象
class User {
public $name;
public $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
}
$user = new User("张三", 25);
$serialized = serialize($user);
echo $serialized;
// 输出: O:4:"User":2:{s:4:"name";s:6:"张三";s:3:"age";i:25;}
?>
14.3 序列化格式说明
a - array
O - object
s - string
i - integer
b - boolean
N - null
d - double
示例解析:
a:2:{s:4:"name";s:6:"张三";s:3:"age";i:25;}
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ └─ 值: 25
│ │ │ │ │ │ └─── 类型: integer
│ │ │ │ │ └──────── 键: age
│ │ │ │ └─────────── 键长度: 3
│ │ │ └────────────────── 值: 张三
│ │ └──────────────────── 值长度: 6
│ └──────────────────────── 键: name
└────────────────────────── 键长度: 4
14.4 反序列化漏洞
<?php
// 危险示例:反序列化用户可控数据
$data = $_GET['data'];
$obj = unserialize($data); // 危险!
// 安全示例:限制反序列化的类
$obj = unserialize($data, ["allowed_classes" => ["SafeClass"]]);
// 漏洞原理
class Evil {
public function __destruct() {
// 当对象被销毁时执行恶意代码
system($_GET['cmd']);
}
}
// 攻击者构造的payload
// O:4:"Evil":0:{}
// 反序列化时会创建Evil对象,脚本结束时触发__destruct
?>
防御措施:
- 不要反序列化不可信的数据
- 使用
json_encode/json_decode 替代
- 使用
allowed_classes 白名单限制
第十五章 PHP数据库操作
15.1 MySQLi 连接
<?php
// 创建连接
$conn = new mysqli("localhost", "root", "password", "mydb");
// 检查连接
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 设置字符集
$conn->set_charset("utf8");
// 执行查询
$sql = "SELECT * FROM users";
$result = $conn->query($sql);
// 获取结果
while ($row = $result->fetch_assoc()) {
echo $row['name'] . "\n";
}
// 关闭连接
$conn->close();
?>
15.2 PDO 连接(推荐)
<?php
try {
// 创建PDO连接
$dsn = "mysql:host=localhost;dbname=mydb;charset=utf8";
$pdo = new PDO($dsn, "root", "password");
// 设置错误模式为异常
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 预处理语句(防止SQL注入)
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $id);
$id = 1;
$stmt->execute();
// 获取结果
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
} catch (PDOException $e) {
echo "数据库错误: " . $e->getMessage();
}
?>
15.3 CRUD 操作
<?php
$pdo = new PDO("mysql:host=localhost;dbname=mydb", "root", "password");
// 插入数据
$sql = "INSERT INTO users (name, email) VALUES (?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute(["张三", "zhangsan@example.com"]);
echo "插入ID: " . $pdo->lastInsertId();
// 查询数据
$stmt = $pdo->query("SELECT * FROM users");
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 更新数据
$sql = "UPDATE users SET name = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute(["李四", 1]);
echo "影响行数: " . $stmt->rowCount();
// 删除数据
$sql = "DELETE FROM users WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([1]);
?>
15.4 事务处理
<?php
try {
$pdo->beginTransaction();
$pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
$pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
$pdo->commit();
echo "转账成功";
} catch (Exception $e) {
$pdo->rollBack();
echo "转账失败: " . $e->getMessage();
}
?>
第十六章 PHP会话管理
16.1 Cookie 操作
<?php
// 设置Cookie
setcookie("username", "张三", time() + 3600, "/"); // 1小时后过期
// 设置带更多参数的Cookie
setcookie(
"token", // 名称
"abc123", // 值
time() + 86400, // 过期时间
"/", // 路径
"example.com", // 域名
true, // 仅HTTPS
true // HttpOnly(防止XSS)
);
// 读取Cookie
echo $_COOKIE['username'];
// 删除Cookie
setcookie("username", "", time() - 3600);
// 检查Cookie是否存在
if (isset($_COOKIE['username'])) {
echo "Cookie存在";
}
?>
16.2 Session 操作
<?php
// 启动Session
session_start();
// 设置Session
$_SESSION['user_id'] = 1;
$_SESSION['username'] = "张三";
$_SESSION['login_time'] = time();
// 读取Session
echo $_SESSION['username'];
// 删除单个Session
unset($_SESSION['username']);
// 销毁所有Session
session_destroy();
// 检查Session是否存在
if (isset($_SESSION['user_id'])) {
echo "用户已登录";
}
?>
16.3 登录认证示例
<?php
session_start();
// 登录处理
function login($username, $password) {
global $pdo;
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['login_time'] = time();
// 记住登录(可选)
if (isset($_POST['remember'])) {
setcookie("remember_token", generateToken(), time() + 86400 * 30);
}
return true;
}
return false;
}
// 检查登录状态
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
// 登出
function logout() {
session_destroy();
setcookie("remember_token", "", time() - 3600);
header("Location: login.php");
}
// 密码加密
$hashed = password_hash("password123", PASSWORD_DEFAULT);
// 密码验证
if (password_verify("password123", $hashed)) {
echo "密码正确";
}
?>
16.4 Session安全配置
<?php
// 安全配置(在session_start之前)
ini_set('session.cookie_httponly', 1); // 防止JS读取Cookie
ini_set('session.cookie_secure', 1); // 仅HTTPS传输
ini_set('session.cookie_samesite', 'Strict'); // 防止CSRF
ini_set('session.use_strict_mode', 1); // 防止Session固定攻击
session_start();
// Session固定攻击防护
if (!isset($_SESSION['initiated'])) {
session_regenerate_id(true);
$_SESSION['initiated'] = true;
}
?>
附录
附录A:PHP超全局变量
| 变量 |
说明 |
$_GET |
GET请求参数 |
$_POST |
POST请求参数 |
$_REQUEST |
GET + POST + COOKIE |
$_FILES |
上传文件信息 |
$_COOKIE |
Cookie数据 |
$_SESSION |
Session数据 |
$_SERVER |
服务器信息 |
$_ENV |
环境变量 |
$GLOBALS |
全局变量 |
附录B:常用PHP配置项
| 配置项 |
说明 |
display_errors |
是否显示错误 |
error_reporting |
错误报告级别 |
log_errors |
是否记录日志 |
upload_max_filesize |
上传文件最大大小 |
post_max_size |
POST数据最大大小 |
max_execution_time |
脚本最大执行时间 |
memory_limit |
脚本内存限制 |