PHP后端开发学习笔记

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
?>

防御措施:

  1. 不要反序列化不可信的数据
  2. 使用 json_encode/json_decode 替代
  3. 使用 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会话管理

<?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 脚本内存限制
posted @ 2026-02-28 16:50  丝云戏千鹤  阅读(17)  评论(0)    收藏  举报