PHP8 编程入门课程

1.PHP 8 概述与环境搭建

一、PHP 8 核心概述

1.1 PHP 是什么?

PHP 全称:Hypertext Preprocessor(超文本预处理器),注意这是一个递归缩写,最初是 Personal Home Page Tools 的缩写,后改为现在的官方全称。

PHP(Hypertext Preprocessor,超文本预处理器)是一门开源的服务器端脚本语言,专门用于 Web 开发:

  • 核心定位:嵌入 HTML 中执行,负责处理服务端逻辑(如数据库交互、用户登录验证、数据计算等)。
  • 应用场景:网站开发(博客 / 电商 / 管理系统)、CLI 脚本(定时任务 / 数据处理)、API 接口开发。
  • 生态优势:语法简单易上手、开源免费、丰富的扩展库(MySQL/Redis/ 图像处理等)、跨平台(Windows/Linux/Mac)。

1.2 PHP 8 的核心改进(重点)

PHP 8 是 PHP 语言的里程碑版本,相比 7.x 系列,主要提升集中在 性能、类型安全、语法简化 三大方向:

表格

改进方向 核心特性 价值
性能提升 JIT 编译器(Just-In-Time)、底层算法优化 CPU 密集型任务性能提升 20%-30%,Web 场景性能提升约 10%
类型安全增强 联合类型、混合类型、never 类型、严格类型模式 减少运行时错误,代码可读性 / 可维护性提升,适配大型项目开发
语法简化 命名参数、match 表达式、空安全运算符、构造函数属性提升 代码量减少,写法更简洁直观
错误处理优化 致命错误转为异常、异常链支持 错误捕获更全面,程序稳定性提升
废弃特性 移除 ereg 扩展、$HTTP_RAW_POST_DATA 等过时特性 简化语言核心,减少历史包袱

1.3 PHP 8.x 版本演进

  • 8.0(2020.11):核心新特性(JIT、联合类型、match 等)的首次发布。
  • 8.1(2021.11):新增枚举(Enum)、只读属性、纤程(Fiber)等。
  • 8.2(2022.12):新增 Disjunctive Normal Form 类型、弃用动态属性等。
  • 8.3(2023.11):新增类型化常量、数组解包优化、json_validate () 函数等。
  • 学习建议:优先掌握 8.0-8.1 的核心特性,8.2+ 特性按需学习。

二、PHP 8 环境搭建

2.1 环境选择(新手友好 + 生产级)

方案 1:一键集成环境(新手首选)
  • Windows:XAMPP、WAMP、PhpStudy(集成 Apache/Nginx + PHP + MySQL,一键启动)。
  • Mac:MAMP、XAMPP for Mac。
  • 优势:无需手动配置,5 分钟搞定,自带管理面板,适合入门学习。
方案 2:Docker 容器(生产级推荐)
  • 优势:环境隔离、版本灵活切换、与生产环境一致,避免「本地能跑,服务器报错」。
  • 前提:先安装 Docker Desktop(Windows/Mac 直接下载安装包,Linux 按官方教程)。

2.2 实操步骤(分方案讲解)

方案 1:XAMPP 搭建 PHP 8 环境(Windows 示例)
  1. 下载安装包

  2. 安装与配置

    • 双击安装包,一路「Next」(建议安装路径选非中文目录,如 D:\xampp)。
    • 安装完成后,打开 XAMPP Control Panel,启动 ApacheMySQL(端口默认 80/3306,若端口被占用可修改)。
  3. 验证环境

    • 打开浏览器,访问 http://localhosthttp://127.0.0.1,能看到 XAMPP 欢迎页即 Apache 正常。
    • 在 XAMPP 的 htdocs 目录(如 D:\xampp\htdocs)新建文件 info.php,内容如下:
    php 复制代码
    <?php
    // 输出 PHP 环境信息,重点看 PHP 版本
    phpinfo();
    ?>
    • 访问 http://localhost/info.php,页面中能看到「PHP Version 8.x.x」即 PHP 8 环境搭建成功。
方案 2:Docker 搭建 PHP 8 环境(通用)
  1. 编写 docker-compose.yml 在本地新建文件夹(如 php8-learn),创建 docker-compose.yml 文件,内容如下:

    yaml

    复制代码
    version: '3.8'
    services:
      # PHP + Nginx 容器
      web:
        image: php:8.1-fpm-nginx
        ports:
          - "8080:80"  # 本地 8080 端口映射到容器 80 端口
        volumes:
          # 本地代码目录映射到容器的网站根目录
          - ./www:/var/www/html
        restart: always
      # MySQL 容器(可选,用于数据库操作)
      mysql:
        image: mysql:8.0
        ports:
          - "3306:3306"
        environment:
          - MYSQL_ROOT_PASSWORD=123456  # root 密码
          - MYSQL_DATABASE=php8_demo    # 初始化数据库
        volumes:
          - ./mysql-data:/var/lib/mysql
        restart: always
  2. 启动容器

    • 打开终端(Windows 用 PowerShell,Mac/Linux 用终端),进入 docker-compose.yml 所在目录。

    • 执行命令启动容器:

      docker-compose up -d

  3. 验证环境

    • php8-learn 目录下新建 www 文件夹,创建 info.php(内容同方案 1)。
    • 访问 http://localhost:8080/info.php,能看到 PHP 8.1 版本信息即环境成功。

2.3 开发工具配置

推荐工具:VS Code(免费)
  1. 安装 VS Code:官网 https://code.visualstudio.com/
  2. 安装必备插件:
    • PHP Intelephense(代码提示、语法检查)。
    • PHP Debug(配合 Xdebug 调试)。
    • EditorConfig for VS Code(统一代码格式)。
  3. 配置 PHP 路径(可选):
    • 打开 VS Code 设置,搜索「PHP Path」,填写 PHP 可执行文件路径(如 XAMPP 的 D:\xampp\php\php.exe)。
备选工具:PhpStorm(付费,功能更强)

三、环境验证与常见问题解决

3.1 核心验证点

  • 执行 php -v 命令(XAMPP 需进入 php 目录,Docker 需进入容器),输出 PHP 8.x 版本。
  • 访问 info.php 确认 PHP 版本、扩展(如 mysqli、PDO)是否正常加载。

3.2 常见问题

  1. Apache 启动失败:大概率是 80 端口被占用(如 IIS、微信开发工具),可在 XAMPP 面板修改 Apache 端口(如改为 8080)。
  2. PHP 扩展未加载 :在 php.ini 中取消对应扩展注释(如 extension=mysqli),重启 Apache/PHP-FPM。
  3. Docker 容器启动失败 :检查端口是否被占用,或删除旧容器后重新启动(docker-compose down && docker-compose up -d)。

2.PHP 基本语法规则

1.1 PHP 代码的执行边界

PHP 是嵌入式脚本语言,代码需用 <?php ?> 标记包裹(短标签 <? ?> 不推荐,需配置开启,兼容性差):

php 复制代码
<?php
// 这是 PHP 代码区域
echo "Hello PHP 8!"; // 输出内容到浏览器/控制台
?>

<!-- HTML 与 PHP 混合示例 -->
<p>当前时间:<?php echo date('Y-m-d H:i:s'); ?></p>
  • 关键说明
    • PHP 文件后缀通常为 .php
    • 代码末尾的 ?> 在纯 PHP 文件中可省略(推荐),避免多余空格导致 header 报错;
    • PHP 代码区分大小写(变量名敏感,关键字 / 函数名不敏感)
php 复制代码
<?php
$name = "PHP";
echo $Name; // 未定义,输出空(变量名区分大小写)
ECHO $name; // 正常输出 "PHP"(echo 关键字不区分大小写)

1.2 注释规则

注释不执行,用于解释代码,分两种类型:

php 复制代码
<?php
// 单行注释(推荐,简洁)
# 单行注释(兼容 shell 风格,少用)

/*
  多行注释
  适合大段说明
  注意:多行注释不能嵌套
*/
echo "注释不影响代码执行";

1.3 语句结束符

PHP 语句必须以分号 ; 结尾(最后一条语句的分号可省略,但推荐统一添加,避免后续追加代码出错):

php 复制代码
<?php
$a = 10; // 变量赋值,分号结尾
$b = 20;
echo $a + $b; // 输出 30,分号结尾

1.4 变量规则

变量是存储数据的容器,PHP 变量有明确的语法规则:

(1)定义规则
  • $ 开头,后跟字母 / 下划线,再跟字母 / 数字 / 下划线;
  • 不能以数字开头,不能包含特殊字符(如 -@);
  • 区分大小写($name$Name)。
php 复制代码
<?php
$username = "张三"; // 合法
$age = 25;         // 合法
$_score = 95.5;    // 合法
// $123abc = 100;  // 非法(以数字开头)
// $user-name = "李四"; // 非法(包含减号)
(2)数据类型

PHP 是弱类型语言(变量类型由赋值决定),核心类型如下:

类型分类 具体类型 示例 PHP 8 补充
标量类型 字符串(string) $str = "PHP8" 支持原生字符串(<<<EOD
整数(int) $num = 100 支持二进制(0b1010
浮点数(float) $price = 99.9 精度问题需注意
布尔值(bool) $is_ok = true true/false 不区分大小写
复合类型 数组(array) $arr = [1,2,3] 短数组语法([])推荐
对象(object) $obj = new stdClass PHP 8 枚举(Enum)归为此类
特殊类型 空值(null) $n = null null 一个值
资源(resource) 数据库连接、文件句柄 现代 PHP 逐渐弱化
(3)常量规则

常量是一旦定义就不可修改的量,PHP 8 支持多种定义方式:

php 复制代码
<?php
// 传统方式(全局常量)
define("PI", 3.14159);
echo PI; // 输出 3.14159

// 类内常量(PHP 5.3+)
class Math {
    const MAX = 100;
    // PHP 8.2+ 类型化常量
    const int MIN = 0;
}
echo Math::MAX; // 输出 100

// PHP 8.1+ 枚举(特殊常量)
enum Status {
    case SUCCESS;
    case FAILED;
}
echo Status::SUCCESS->name; // 输出 SUCCESS

1.5 运算符与流程控制

(1)常用运算符
类型 示例 说明
算术运算符 +-*/% 加减乘除、取余
赋值运算符 =+=*= $a += 5 等价于 $a = $a+5
比较运算符 ==(值相等)、===(全等) 0 == "0" 为 true,0 === "0" 为 false
逻辑运算符 &&、|| ! 与、或、非
(2)流程控制

核心用于控制代码执行顺序,新手必掌握:

php 复制代码
<?php
// 1. 条件判断
$score = 85;
if ($score >= 90) {
    echo "优秀";
} elseif ($score >= 70) {
    echo "良好";
} else {
    echo "及格";
}

// PHP 8 match 表达式(替代 switch,更简洁)
$status = 1;
$result = match ($status) {
    1 => "成功",
    2 => "失败",
    3 => "处理中",
    default => "未知状态",
};
echo $result; // 输出 "成功"

// 2. 循环
// for 循环
for ($i = 1; $i <= 5; $i++) {
    echo $i . " "; // 输出 1 2 3 4 5
}

// foreach 循环(遍历数组)
$fruits = ["苹果", "香蕉", "橙子"];
foreach ($fruits as $index => $fruit) {
    echo "索引{$index}:{$fruit} <br>";
}

3.函数基础

函数是封装可复用代码的模块,PHP 函数分为「内置函数」和「自定义函数」。

2.1 函数定义规则

php 复制代码
<?php
/**
 * 自定义函数模板
 * @param 类型 $参数名  参数说明
 * @return 类型         返回值说明
 */
function 函数名(参数列表) {
    // 函数体(要执行的代码)
    return 返回值; // 可选,无 return 则返回 null
}
  • 核心规则
    1. 函数名以字母 / 下划线开头,不区分大小写(推荐小写 + 下划线命名);
    2. 参数可指定默认值(默认参数需放在非默认参数后);
    3. PHP 8 支持「类型提示」(指定参数 / 返回值类型),增强类型安全。
基础示例
php 复制代码
<?php
// 无参数、无返回值
function sayHello() {
    echo "Hello PHP!<br>";
}
sayHello(); // 调用函数,输出 Hello PHP!

// 有参数、有返回值(PHP 8 类型提示)
function add(int $a, int $b): int {
    return $a + $b;
}
echo add(5, 3); // 输出 8

// 默认参数
function greet(string $name = "访客"): string {
    return "你好,{$name}!";
}
echo greet(); // 输出 你好,访客!
echo greet("张三"); // 输出 你好,张三!

// PHP 8 命名参数(调用时指定参数名,无需按顺序)
echo greet(name: "李四"); // 输出 你好,李四!

2.2 变量作用域

变量的作用域指变量可被访问的范围,核心分为 3 类:

php 复制代码
<?php
$global_var = "全局变量"; // 全局变量(函数外定义)

function testScope() {
    $local_var = "局部变量"; // 局部变量(函数内定义,外部不可访问)
    echo $local_var . "<br>"; // 正常输出
    
    // 访问全局变量:需用 global 关键字或 $GLOBALS 数组
    global $global_var;
    echo $global_var . "<br>"; // 正常输出
    
    // 静态变量(函数执行后保留值)
    static $count = 0;
    $count++;
    echo "计数:{$count}<br>";
}

testScope(); // 输出 局部变量 + 全局变量 + 计数:1
testScope(); // 输出 局部变量 + 全局变量 + 计数:2(静态变量保留了 1)
// echo $local_var; // 报错:未定义变量(局部变量外部不可访问)

2.3 内置函数使用

PHP 内置了数千个函数,覆盖字符串、数组、文件等场景,无需定义可直接调用:

(1)字符串函数
php 复制代码
<?php
$str = "PHP 8 基础语法";
echo strlen($str); // 输出 8(字符串长度)
echo strtoupper($str); // 输出 PHP 8 基础语法(转大写)
echo str_replace("8", "八", $str); // 输出 PHP 八 基础语法(替换)
(2)数组函数
php 复制代码
<?php
$arr = [3, 1, 2];
sort($arr); // 升序排序
print_r($arr); // 输出 Array ( [0] => 1 [1] => 2 [2] => 3 )
echo count($arr); // 输出 3(数组长度)
echo in_array(2, $arr); // 输出 1(true,判断元素是否存在)
(3)PHP 8 新增内置函数
php 复制代码
<?php
// json_validate()(PHP 8.3+):验证 JSON 字符串是否合法
$json = '{"name":"PHP8"}';
var_dump(json_validate($json)); // 输出 bool(true)

// str_contains()(PHP 8.0+):判断字符串是否包含子串
var_dump(str_contains("PHP8", "8")); // 输出 bool(true)

2.4 函数进阶(PHP 8 特性)

(1)联合类型参数

允许参数接收多种类型的值:

复制代码
<?php
// PHP 8 联合类型:参数可以是 int 或 string
function showValue(int|string $value): void {
    echo "值:{$value}<br>";
}
showValue(100); // 输出 值:100
showValue("PHP"); // 输出 值:PHP
(2)Never 类型返回值

表示函数永不返回(如抛异常、死循环):

复制代码
<?php
function error(string $msg): never {
    echo "错误:{$msg}";
    exit; // 终止程序,永不返回
}
// error("参数错误"); // 执行后程序终止

练习:

编写一个 PHP 8 程序,实现以下核心功能:

  • 定义函数 calculateScore(array $scores): array,接收学生单科成绩数组(支持整数 / 浮点数);
  • 过滤数组中非数值类型的成绩(如字符串、布尔值等无效数据);
  • 计算有效成绩的平均分(保留 1 位小数);
  • 使用 PHP 8 的 match 表达式根据平均分判断成绩等级:
    • 90 分及以上:优秀
    • 80-89 分:良好
    • 60-79 分:及格
    • 60 分以下:不及格
  • 函数返回包含「平均分」「等级」「有效成绩数量」的关联数组。
php 复制代码
<?php
/**
 * 实战:计算学生平均分,判断等级
 * 涵盖变量、数组、循环、函数、PHP 8 类型提示
 */
function calculateScore(array $scores): array {
    $total = 0;
    $count = count($scores);
    
    // 遍历计算总分
    foreach ($scores as $score) {
        // 过滤非数值类型(PHP 8 类型提示仅在严格模式生效)
        if (!is_numeric($score)) {
            continue;
        }
        $total += $score;
    }
    
    // 计算平均分
    $average = $count > 0 ? $total / $count : 0;
    
    // 判断等级(PHP 8 match 表达式)
    $level = match (true) {
        $average >= 90 => "优秀",
        $average >= 80 => "良好",
        $average >= 60 => "及格",
        default => "不及格",
    };
    
    return [
        "平均分" => round($average, 1), // 保留 1 位小数
        "等级" => $level
    ];
}

// 调用函数
$studentScores = [85, 92, 78, 90];
$result = calculateScore($studentScores);

// 输出结果
echo "学生成绩分析:<br>";
echo "平均分:{$result['平均分']}<br>";
echo "等级:{$result['等级']}<br>";
// 输出:平均分:86.2,等级:良好

4.PHP 8 MySQL数据库操作

一、核心知识点概述

PHP 操作 MySQL 数据库的主流方式有两种,均适配 PHP 8:

表格

方式 特点 适用场景
MySQLi 仅支持 MySQL,分面向过程 / 面向对象写法,PHP 8 优化了错误处理 仅使用 MySQL 的简单项目
PDO 支持多数据库(MySQL/Oracle/PostgreSQL 等),仅面向对象,安全性更高 跨数据库项目、企业级开发

核心原则:无论使用哪种方式,都必须使用「预处理语句」防止 SQL 注入,这是 Web 开发的基础安全要求。

二、环境准备

  1. 确保 PHP 环境已启用相关扩展:
    • MySQLi 扩展:extension=mysqli(php.ini 中取消注释,PHP 8 默认启用);
    • PDO 扩展:extension=pdo_mysql(php.ini 中取消注释)。
  2. 验证扩展是否启用:创建 phpinfo.php,查看 mysqliPDO 模块是否存在。
  3. 准备测试数据库 / 表:
sql 复制代码
-- 创建数据库
CREATE DATABASE IF NOT EXISTS php8_demo DEFAULT CHARSET utf8mb4;
USE php8_demo;

-- 创建学生表
CREATE TABLE IF NOT EXISTS students (
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
    name VARCHAR(50) NOT NULL COMMENT '姓名',
    age TINYINT UNSIGNED NOT NULL COMMENT '年龄',
    score FLOAT NOT NULL COMMENT '成绩',
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) COMMENT '学生信息表';

三、MySQLi 面向对象操作(PHP 8 版)

3.1 数据库连接

php 复制代码
<?php
/**
 * MySQLi 连接数据库(PHP 8 错误处理)
 * @return mysqli 数据库连接对象
 */
function connectMysql(): mysqli {
    // 数据库配置(建议抽离到配置文件)
    $host = 'localhost';
    $user = 'root';
    $password = '123456';
    $dbname = 'php8_demo';
    $charset = 'utf8mb4';

    // 建立连接(PHP 8 支持严格类型,连接失败抛出 Error 异常)
    try {
        $mysqli = new mysqli($host, $user, $password, $dbname);
        // 检查连接错误
        if ($mysqli->connect_errno) {
            throw new Exception("数据库连接失败:{$mysqli->connect_error}");
        }
        // 设置字符集
        $mysqli->set_charset($charset);
        return $mysqli;
    } catch (Exception $e) {
        die("错误:{$e->getMessage()}");
    }
}

// 测试连接
$mysqli = connectMysql();
echo "MySQLi 数据库连接成功!<br>";

3.2 CRUD 核心操作(预处理语句)

(1)新增数据(CREATE)
php 复制代码
<?php
// 1. 连接数据库
$mysqli = connectMysql();

// 2. 准备预处理语句(? 是占位符)
$sql = "INSERT INTO students (name, age, score) VALUES (?, ?, ?)";
$stmt = $mysqli->prepare($sql);

// 3. 绑定参数(s=字符串,i=整数,d=浮点数)
$name = "张三";
$age = 18;
$score = 92.5;
// PHP 8 支持类型提示,绑定参数时自动匹配类型
$stmt->bind_param("sid", $name, $age, $score);

// 4. 执行语句
if ($stmt->execute()) {
    echo "新增成功,自增ID:{$mysqli->insert_id}<br>";
} else {
    echo "新增失败:{$stmt->error}<br>";
}

// 5. 关闭资源
$stmt->close();
$mysqli->close();
(2)查询数据(READ)
php 复制代码
<?php
// 1. 连接数据库
$mysqli = connectMysql();

// 2. 准备预处理语句(查询年龄≥18的学生)
$sql = "SELECT id, name, age, score FROM students WHERE age >= ?";
$stmt = $mysqli->prepare($sql);

// 3. 绑定参数并执行
$minAge = 18;
$stmt->bind_param("i", $minAge);
$stmt->execute();

// 4. 绑定结果集(将查询结果绑定到变量)
$stmt->bind_result($id, $name, $age, $score);

// 5. 遍历结果
echo "<h3>学生列表(年龄≥18)</h3>";
echo "<ul>";
while ($stmt->fetch()) {
    echo "<li>ID:{$id},姓名:{$name},年龄:{$age},成绩:{$score}</li>";
}
echo "</ul>";

// 6. 关闭资源
$stmt->close();
$mysqli->close();
(3)更新数据(UPDATE)
php 复制代码
<?php
// 1. 连接数据库
$mysqli = connectMysql();

// 2. 准备预处理语句(更新ID=1的学生成绩)
$sql = "UPDATE students SET score = ? WHERE id = ?";
$stmt = $mysqli->prepare($sql);

// 3. 绑定参数并执行
$newScore = 95.0;
$id = 1;
$stmt->bind_param("di", $newScore, $id);

if ($stmt->execute()) {
    echo "更新成功,影响行数:{$stmt->affected_rows}<br>";
} else {
    echo "更新失败:{$stmt->error}<br>";
}

// 4. 关闭资源
$stmt->close();
$mysqli->close();
(4)删除数据(DELETE)
php 复制代码
<?php
// 1. 连接数据库
$mysqli = connectMysql();

// 2. 准备预处理语句(删除ID=1的学生)
$sql = "DELETE FROM students WHERE id = ?";
$stmt = $mysqli->prepare($sql);

// 3. 绑定参数并执行
$id = 1;
$stmt->bind_param("i", $id);

if ($stmt->execute()) {
    echo "删除成功,影响行数:{$stmt->affected_rows}<br>";
} else {
    echo "删除失败:{$stmt->error}<br>";
}

// 4. 关闭资源
$stmt->close();
$mysqli->close();

四、PDO 操作(PHP 8 推荐)

PDO 是 PHP 数据对象(PHP Data Objects),支持多数据库,是 PHP 8 企业级开发的首选方式。

4.1 数据库连接

php 复制代码
<?php
/**
 * PDO 连接数据库(PHP 8 异常处理)
 * @return PDO 数据库连接对象
 */
function connectPdo(): PDO {
    // 数据库配置
    $dsn = 'mysql:host=localhost;dbname=php8_demo;charset=utf8mb4';
    $user = 'root';
    $password = '123456';
    // PDO 选项(关键:启用异常模式、关闭模拟预处理)
    $options = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // PHP 8 推荐异常模式
        PDO::ATTR_EMULATE_PREPARES => false, // 禁用模拟预处理,使用数据库原生预处理
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC // 默认关联数组返回结果
    ];

    try {
        $pdo = new PDO($dsn, $user, $password, $options);
        return $pdo;
    } catch (PDOException $e) {
        die("PDO 连接失败:{$e->getMessage()}");
    }
}

// 测试连接
$pdo = connectPdo();
echo "PDO 数据库连接成功!<br>";

4.2 CRUD 核心操作(预处理语句)

(1)新增数据(CREATE)
php 复制代码
<?php
// 1. 连接数据库
$pdo = connectPdo();

// 2. 准备预处理语句(命名占位符 :name 更易读)
$sql = "INSERT INTO students (name, age, score) VALUES (:name, :age, :score)";
$stmt = $pdo->prepare($sql);

// 3. 绑定参数并执行(PHP 8 支持数组直接传参)
$params = [
    ':name' => '李四',
    ':age' => 19,
    ':score' => 88.5
];
if ($stmt->execute($params)) {
    // 获取自增ID(PHP 8 兼容)
    $lastId = $pdo->lastInsertId();
    echo "新增成功,自增ID:{$lastId}<br>";
}

// 4. 关闭语句(可选,PHP 会自动回收)
$stmt->closeCursor();
(2)查询数据(READ)
php 复制代码
<?php
// 1. 连接数据库
$pdo = connectPdo();

// 2. 准备预处理语句(查询成绩≥80的学生)
$sql = "SELECT id, name, age, score FROM students WHERE score >= :min_score";
$stmt = $pdo->prepare($sql);

// 3. 执行语句
$stmt->execute([':min_score' => 80]);

// 4. 获取结果(3种方式)
// 方式1:获取单条
// $student = $stmt->fetch();
// 方式2:获取所有(推荐)
$students = $stmt->fetchAll();
// 方式3:遍历
// while ($student = $stmt->fetch()) {}

// 输出结果
echo "<h3>成绩≥80的学生列表</h3>";
echo "<ul>";
foreach ($students as $stu) {
    echo "<li>ID:{$stu['id']},姓名:{$stu['name']},成绩:{$stu['score']}</li>";
}
echo "</ul>";
(3)更新数据(UPDATE)
php 复制代码
<?php
// 1. 连接数据库
$pdo = connectPdo();

// 2. 准备预处理语句
$sql = "UPDATE students SET age = :age WHERE id = :id";
$stmt = $pdo->prepare($sql);

// 3. 执行语句
$params = [':age' => 20, ':id' => 2];
$stmt->execute($params);
echo "更新成功,影响行数:{$stmt->rowCount()}<br>";
(4)删除数据(DELETE)
php 复制代码
<?php
// 1. 连接数据库
$pdo = connectPdo();

// 2. 准备预处理语句
$sql = "DELETE FROM students WHERE id = :id";
$stmt = $pdo->prepare($sql);

// 3. 执行语句
$stmt->execute([':id' => 2]);
echo "删除成功,影响行数:{$stmt->rowCount()}<br>";

五、PHP 8 特性优化数据库操作

5.1 类型提示增强

php 复制代码
<?php
/**
 * PHP 8 严格类型:新增学生数据
 * @param PDO $pdo 数据库连接对象
 * @param string $name 姓名
 * @param int $age 年龄
 * @param float $score 成绩
 * @return int 新增数据的ID
 */
function addStudent(PDO $pdo, string $name, int $age, float $score): int {
    $sql = "INSERT INTO students (name, age, score) VALUES (:name, :age, :score)";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([
        ':name' => $name,
        ':age' => $age,
        ':score' => $score
    ]);
    return (int)$pdo->lastInsertId(); // PHP 8 强制类型转换更严格
}

// 调用(类型不匹配会直接报错,提前拦截错误)
$pdo = connectPdo();
$id = addStudent($pdo, "王五", 21, 91.0);
echo "新增学生ID:{$id}<br>";

5.2 联合类型处理空值

php 复制代码
<?php
/**
 * PHP 8 联合类型:根据ID查询学生
 * @param PDO $pdo 数据库连接对象
 * @param int $id 学生ID
 * @return array|null 学生信息(null 表示无数据)
 */
function getStudentById(PDO $pdo, int $id): array|null {
    $sql = "SELECT * FROM students WHERE id = :id";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([':id' => $id]);
    return $stmt->fetch() ?: null; // 无数据返回 null
}

// 调用
$student = getStudentById($pdo, 3);
if ($student) {
    echo "学生姓名:{$student['name']}<br>";
} else {
    echo "未找到该学生<br>";
}

六、核心安全:防止 SQL 注入

为什么预处理语句能防注入?

  • 普通拼接 SQL 存在注入风险:

    php 复制代码
    // 危险!用户输入 `1 OR 1=1` 会查询所有数据
    $id = $_GET['id'];
    $sql = "SELECT * FROM students WHERE id = $id"; 
  • 预处理语句将「SQL 结构」和「数据」分离,数据会被数据库自动转义,杜绝注入:

    php 复制代码
    // 安全!无论 $id 输入什么,都会被当作普通数据处理
    $stmt = $pdo->prepare("SELECT * FROM students WHERE id = :id");
    $stmt->execute([':id' => $id]);

七、实战示例:学生成绩管理系统(PDO 版)

php 复制代码
<?php
// 封装数据库操作类(PHP 8 面向对象)
class StudentManager {
    private PDO $pdo; // PHP 8 类属性类型提示

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    // 新增学生
    public function add(string $name, int $age, float $score): int {
        $sql = "INSERT INTO students (name, age, score) VALUES (:name, :age, :score)";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(compact('name', 'age', 'score'));
        return (int)$this->pdo->lastInsertId();
    }

    // 批量查询
    public function list(int $page = 1, int $size = 10): array {
        $offset = ($page - 1) * $size;
        $sql = "SELECT * FROM students LIMIT :offset, :size";
        $stmt = $this->pdo->prepare($sql);
        // 数值类型需显式绑定(PDO 对 LIMIT 占位符的特殊处理)
        $stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
        $stmt->bindParam(':size', $size, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll();
    }

    // 删除学生
    public function delete(int $id): bool {
        $sql = "DELETE FROM students WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(compact('id'));
        return $stmt->rowCount() > 0;
    }
}

// 调用示例
try {
    $pdo = connectPdo();
    $manager = new StudentManager($pdo);

    // 新增学生
    $id = $manager->add("赵六", 22, 85.5);
    echo "新增学生ID:{$id}<br>";

    // 查询第1页学生(每页10条)
    $students = $manager->list();
    echo "<h3>学生列表</h3>";
    foreach ($students as $stu) {
        echo "ID:{$stu['id']},姓名:{$stu['name']},年龄:{$stu['age']}<br>";
    }

    // 删除学生
    $isDeleted = $manager->delete($id);
    echo $isDeleted ? "删除成功<br>" : "删除失败<br>";
} catch (PDOException $e) {
    echo "操作失败:{$e->getMessage()}";
}

5.PHP 8 Web 开发核心(从请求到响应)

一、Web 开发核心流程概述

PHP 作为服务器端脚本语言,核心作用是处理客户端 HTTP 请求执行服务端逻辑 (如数据库操作、数据计算) → 生成 HTTP 响应(HTML/JSON 等)返回给客户端。

核心流程示意图:

二、HTTP 与 PHP 交互核心

2.1 超全局变量(PHP 8 兼容)

超全局变量是 PHP 预定义的、可在脚本任意位置访问的数组,核心用于接收客户端请求数据:

变量名 作用 安全注意事项
$_GET 接收 GET 请求参数(URL 中 ?key=value 数据暴露在 URL,不可传敏感信息,需过滤转义
$_POST 接收 POST 请求参数(表单 / JSON 提交) 适合传敏感信息,仍需过滤验证
$_COOKIE 接收客户端 Cookie 数据 可被客户端篡改,仅存储非敏感信息
$_SESSION 接收服务端 Session 数据(基于 Cookie 标识) 服务端存储,相对安全,需注意 Session 劫持防护
$_REQUEST 包含 $_GET/$_POST/$_COOKIE(PHP 8 已优化默认仅包含 GET/POST) 不推荐使用,数据来源不明确,易引发安全问题
$_SERVER 服务器 / 请求信息(如请求方法、客户端 IP、URL 等) 部分字段可被伪造(如 HTTP_X_FORWARDED_FOR),需验证
实战示例:获取请求数据(PHP 8 类型安全)
php 复制代码
<?php
// 开启严格类型(可选,PHP 8 推荐)
declare(strict_types=1);

// 1. 获取 GET 参数(带默认值+类型转换)
$page = $_GET['page'] ?? 1; // PHP 7+ 空合并运算符
$page = (int)$page; // PHP 8 强制类型转换,确保是整数
$keywords = $_GET['keywords'] ?? '';
$keywords = htmlspecialchars($keywords, ENT_QUOTES, 'UTF-8'); // 防 XSS

// 2. 获取 POST 参数(表单提交)
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';

// 3. 获取服务器信息
$requestMethod = $_SERVER['REQUEST_METHOD']; // GET/POST/PUT/DELETE 等
$clientIp = $_SERVER['REMOTE_ADDR']; // 客户端 IP(真实IP需结合反向代理处理)
$currentUrl = $_SERVER['PHP_SELF']; // 当前脚本路径

// 输出示例
echo "请求方法:{$requestMethod}<br>";
echo "当前页码:{$page}<br>";
echo "搜索关键词:{$keywords}<br>";

2.2 HTTP 响应控制

PHP 可直接控制 HTTP 响应的状态码、响应头、输出内容,是 Web 开发的核心能力。

(1)设置 HTTP 状态码
php 复制代码
<?php
// 基础用法:设置 404 页面
http_response_code(404); // PHP 5.4+ 支持,PHP 8 优化了状态码兼容性
echo "<h1>页面不存在(404 Not Found)</h1>";

// 进阶:设置 302 重定向
http_response_code(302);
header('Location: https://www.example.com'); // 重定向到指定 URL
exit; // 重定向后必须终止脚本执行

// REST API 常用状态码
http_response_code(200); // 成功
http_response_code(400); // 参数错误
http_response_code(401); // 未授权
http_response_code(500); // 服务器内部错误
(2)设置响应头(Content-Type 核心)
php 复制代码
<?php
// 1. 返回 HTML 响应(默认)
header('Content-Type: text/html; charset=utf-8');
echo "<h1>这是 HTML 内容</h1>";

// 2. 返回 JSON 响应(API 开发核心)
header('Content-Type: application/json; charset=utf-8');
$data = [
    'code' => 200,
    'msg' => '操作成功',
    'data' => ['name' => 'PHP 8', 'version' => '8.3']
];
echo json_encode($data, JSON_UNESCAPED_UNICODE); // 保留中文不转义
exit;

// 3. 下载文件响应
$filename = 'demo.txt';
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename={$filename}");
header('Content-Length: ' . filesize($filename));
readfile($filename); // 输出文件内容
exit;

三、表单处理与验证(Web 开发高频场景)

表单是客户端向服务端提交数据的核心方式,PHP 8 下需兼顾数据验证安全防护

3.1 表单基础结构(HTML + PHP)

php 复制代码
<!-- form.html / form.php -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>PHP 表单示例</title>
</head>
<body>
    <!-- POST 提交到自身页面处理 -->
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
        <div>
            <label>姓名:</label>
            <input type="text" name="username" required>
        </div>
        <div>
            <label>年龄:</label>
            <input type="number" name="age" min="1" max="120">
        </div>
        <div>
            <label>邮箱:</label>
            <input type="email" name="email">
        </div>
        <div>
            <button type="submit" name="submit">提交</button>
        </div>
    </form>

    <?php
    // PHP 8 表单处理逻辑
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit'])) {
        // 1. 数据过滤(核心:防 XSS、格式验证)
        $username = htmlspecialchars(trim($_POST['username']), ENT_QUOTES);
        $age = (int)$_POST['age'] ?? 0;
        $email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);

        // 2. 业务验证(PHP 8 条件判断优化)
        $errors = [];
        if (empty($username)) $errors[] = '姓名不能为空';
        if ($age < 1 || $age > 120) $errors[] = '年龄需在1-120之间';
        if (!$email) $errors[] = '邮箱格式错误';

        // 3. 验证结果处理
        if (empty($errors)) {
            echo "<p style='color: green;'>提交成功!姓名:{$username},年龄:{$age}</p>";
            // 后续:存入数据库/其他业务逻辑
        } else {
            echo "<p style='color: red;'>提交失败:" . implode('、', $errors) . "</p>";
        }
    }
    ?>
</body>
</html>

3.2 PHP 8 表单验证增强(过滤器 + 类型提示)

PHP 内置 filter 扩展(PHP 8 优化性能),是表单验证的首选工具:

php 复制代码
<?php
/**
 * PHP 8 表单验证函数(类型提示+过滤器)
 * @param array $data 表单提交的原始数据
 * @return array [bool $isValid, array $errors, array $cleanData]
 */
function validateForm(array $data): array {
    $cleanData = [];
    $errors = [];

    // 1. 验证姓名(非空+长度限制)
    $cleanData['username'] = trim($data['username'] ?? '');
    if (empty($cleanData['username'])) {
        $errors[] = '姓名不能为空';
    } elseif (mb_strlen($cleanData['username']) > 20) {
        $errors[] = '姓名长度不能超过20个字符';
    }

    // 2. 验证年龄(整数+范围)
    $cleanData['age'] = filter_var($data['age'] ?? 0, FILTER_VALIDATE_INT, [
        'options' => ['min_range' => 1, 'max_range' => 120]
    ]);
    if ($cleanData['age'] === false) {
        $errors[] = '年龄需为1-120的整数';
        $cleanData['age'] = 0; // 重置无效值
    }

    // 3. 验证手机号(PHP 8 正则匹配)
    $cleanData['phone'] = $data['phone'] ?? '';
    if (!preg_match('/^1[3-9]\d{9}$/', $cleanData['phone'])) {
        $errors[] = '手机号格式错误';
    }

    return [empty($errors), $errors, $cleanData];
}

// 调用示例
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    [$isValid, $errors, $data] = validateForm($_POST);
    if ($isValid) {
        echo "验证通过:{$data['username']} - {$data['phone']}";
    } else {
        echo "验证失败:" . implode('<br>', $errors);
    }
}

HTTP 是无状态协议,Session 和 Cookie 是实现「用户状态保持」的核心方案,PHP 8 对两者的安全性做了优化。

Cookie 是存储在客户端浏览器的小型文本数据,PHP 通过 setcookie()/$_COOKIE 操作:

php 复制代码
<?php
// 1. 设置 Cookie(PHP 8 安全参数优化)
$cookieName = 'user_token';
$cookieValue = md5(uniqid(mt_rand(), true)); // 生成随机令牌
$expire = time() + 3600 * 24 * 7; // 有效期7天
$path = '/'; // 全站可用
$domain = ''; // 域名(如 .example.com)
$secure = false; // HTTPS 环境设为 true
$httponly = true; // 禁止 JS 访问(防 XSS 窃取)
$samesite = 'Lax'; // 防 CSRF(Strict/Lax/None)

// PHP 8 支持通过 header 手动设置(更灵活)
header("Set-Cookie: {$cookieName}={$cookieValue}; Expires=" . gmdate('D, d M Y H:i:s T', $expire) . "; Path={$path}; HttpOnly; SameSite={$samesite}");

// 2. 获取 Cookie
$token = $_COOKIE[$cookieName] ?? '';
echo "Cookie 令牌:{$token}<br>";

// 3. 删除 Cookie(设置过期时间为过去)
setcookie($cookieName, '', time() - 3600, $path, $domain, $secure, $httponly);
unset($_COOKIE[$cookieName]);

4.2 Session 操作(服务端存储)

Session 数据存储在服务端,仅通过 Cookie 传递 PHPSESSID 标识,安全性更高:

php 复制代码
<?php
// 1. Session 配置(PHP 8 推荐在 php.ini 或代码中配置)
ini_set('session.name', 'PHP8_SESSID'); // 自定义 Session ID 名称
ini_set('session.cookie_httponly', '1'); // 禁止 JS 访问
ini_set('session.cookie_samesite', 'Lax'); // 防 CSRF
ini_set('session.gc_maxlifetime', 3600); // Session 有效期1小时
ini_set('session.save_path', '/tmp/php_sessions'); // 自定义存储路径

// 2. 启动 Session(必须在输出任何内容前调用)
session_start();

// 3. 设置 Session 数据
$_SESSION['user_id'] = 1001;
$_SESSION['username'] = 'PHP8用户';
$_SESSION['login_time'] = date('Y-m-d H:i:s');

// 4. 获取 Session 数据(PHP 8 空合并运算符)
$username = $_SESSION['username'] ?? '游客';
echo "当前登录用户:{$username}<br>";

// 5. 修改 Session 数据
$_SESSION['username'] = 'PHP8进阶用户';

// 6. 销毁 Session(退出登录)
// unset($_SESSION['user_id']); // 销毁单个数据
// $_SESSION = []; // 清空所有 Session 数据
// session_destroy(); // 销毁服务端 Session 文件
// setcookie(session_name(), '', time() - 3600, '/'); // 删除客户端 Session ID
实战:用户登录状态保持
php 复制代码
<?php
// login.php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';

    // 模拟验证(实际需查数据库+密码哈希验证)
    if ($username === 'admin' && $password === '123456') {
        // 登录成功,设置 Session
        $_SESSION['is_login'] = true;
        $_SESSION['username'] = $username;
        $_SESSION['login_time'] = time();
        header('Location: index.php'); // 跳转到首页
        exit;
    } else {
        echo "用户名或密码错误";
    }
}
?>

<!-- index.php -->
<?php
session_start();
// 验证登录状态
if (!($_SESSION['is_login'] ?? false)) {
    header('Location: login.php'); // 未登录跳转到登录页
    exit;
}
echo "欢迎回来,{$_SESSION['username']}!<br>";
echo "<a href='logout.php'>退出登录</a>";

// logout.php
session_start();
$_SESSION = [];
session_destroy();
setcookie(session_name(), '', time() - 3600, '/');
header('Location: login.php');
exit;

五、PHP 8 Web 开发安全核心

Web 开发的安全问题是重中之重,PHP 8 提供了更完善的防护机制,核心需关注以下点:

5.1 XSS 防护(跨站脚本攻击)

  • 核心手段:输出数据时用 htmlspecialchars() 转义特殊字符;
  • PHP 8 优化:ENT_QUOTES 模式更稳定,支持 UTF-8 编码;
php 复制代码
<?php
// 危险:直接输出用户输入
// echo $_GET['content'];

// 安全:转义后输出
$content = $_GET['content'] ?? '';
echo htmlspecialchars($content, ENT_QUOTES, 'UTF-8');

5.2 CSRF 防护(跨站请求伪造)

  • 核心手段:生成 CSRF Token 并验证;
php 复制代码
<?php
session_start();

// 生成 CSRF Token
if (!isset($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); // PHP 7+ 安全随机数
}

// 表单中嵌入 Token
echo "<form method='post'>
    <input type='hidden' name='csrf_token' value='{$_SESSION['csrf_token']}'>
    <button type='submit'>提交</button>
</form>";

// 验证 Token
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $token = $_POST['csrf_token'] ?? '';
    if (!hash_equals($_SESSION['csrf_token'], $token)) { // PHP 8 安全比较
        die("CSRF 验证失败!");
    }
    // 正常业务逻辑
}

5.3 密码安全(PHP 8 哈希优化)

  • 禁止明文存储密码,使用 password_hash()/password_verify()(PHP 8 优化算法性能);
php 复制代码
<?php
// 注册:生成密码哈希
$password = '123456';
$hash = password_hash($password, PASSWORD_DEFAULT); // 默认使用 bcrypt 算法
echo "密码哈希:{$hash}<br>";

// 登录:验证密码
$inputPwd = '123456';
if (password_verify($inputPwd, $hash)) {
    echo "密码验证通过<br>";
} else {
    echo "密码错误<br>";
}

六、实战示例:简易用户注册登录系统

php 复制代码
<?php
/**
 * 核心功能:用户注册 + 登录 + 退出
 * 技术点:PHP 8 类型提示、密码哈希、Session、表单验证、PDO 数据库操作
 */
// 1. 初始化配置
declare(strict_types=1);
ini_set('display_errors', '0');
ini_set('session.cookie_httponly', '1');
session_start();

// 2. 数据库连接(复用之前的 PDO 连接函数)
function connectPdo(): PDO {
    $dsn = 'mysql:host=localhost;dbname=php8_demo;charset=utf8mb4';
    $options = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_EMULATE_PREPARES => false
    ];
    return new PDO($dsn, 'root', '123456', $options);
}

// 3. 注册函数
function register(string $username, string $password): array {
    $errors = [];
    // 验证参数
    if (mb_strlen($username) < 3 || mb_strlen($username) > 20) {
        $errors[] = '用户名长度需3-20个字符';
    }
    if (strlen($password) < 6) {
        $errors[] = '密码长度不能少于6位';
    }
    if (!empty($errors)) {
        return [false, $errors];
    }

    // 数据库操作
    try {
        $pdo = connectPdo();
        // 检查用户名是否已存在
        $stmt = $pdo->prepare("SELECT id FROM users WHERE username = :username");
        $stmt->execute([':username' => $username]);
        if ($stmt->fetch()) {
            $errors[] = '用户名已存在';
            return [false, $errors];
        }

        // 插入用户(密码哈希)
        $hash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (:username, :password)");
        $stmt->execute([':username' => $username, ':password' => $hash]);
        return [true, ['注册成功,请登录']];
    } catch (PDOException $e) {
        $errors[] = '数据库错误:' . $e->getMessage();
        return [false, $errors];
    }
}

// 4. 登录函数
function login(string $username, string $password): array {
    $errors = [];
    try {
        $pdo = connectPdo();
        $stmt = $pdo->prepare("SELECT id, password FROM users WHERE username = :username");
        $stmt->execute([':username' => $username]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$user || !password_verify($password, $user['password'])) {
            $errors[] = '用户名或密码错误';
            return [false, $errors];
        }

        // 设置登录状态
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['username'] = $username;
        $_SESSION['is_login'] = true;
        return [true, ['登录成功']];
    } catch (PDOException $e) {
        $errors[] = '数据库错误:' . $e->getMessage();
        return [false, $errors];
    }
}

// 5. 处理请求
$action = $_GET['action'] ?? 'login';
$message = '';
$msgType = 'error';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username'] ?? '');
    $password = trim($_POST['password'] ?? '');

    if ($action === 'register') {
        [$success, $errors] = register($username, $password);
        $msgType = $success ? 'success' : 'error';
        $message = implode('<br>', $errors);
    } elseif ($action === 'login') {
        [$success, $errors] = login($username, $password);
        $msgType = $success ? 'success' : 'error';
        $message = implode('<br>', $errors);
        if ($success) {
            header('Location: ?action=index');
            exit;
        }
    }
}

// 6. 退出登录
if ($action === 'logout') {
    $_SESSION = [];
    session_destroy();
    setcookie(session_name(), '', time() - 3600, '/');
    header('Location: ?action=login');
    exit;
}

// 7. 验证登录状态(首页)
if ($action === 'index') {
    if (!($_SESSION['is_login'] ?? false)) {
        header('Location: ?action=login');
        exit;
    }
    $message = "欢迎你,{$_SESSION['username']}!<br><a href='?action=logout'>退出登录</a>";
    $msgType = 'success';
}
?>

<!-- HTML 页面 -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>PHP 8 用户系统</title>
    <style>
        .success { color: green; }
        .error { color: red; }
        .container { width: 400px; margin: 50px auto; }
        form { margin-top: 20px; }
        input { margin: 5px 0; padding: 8px; width: 100%; }
        button { padding: 10px; width: 100%; background: #007bff; color: white; border: none; }
        a { margin: 0 5px; }
    </style>
</head>
<body>
    <div class="container">
        <h1><?php echo $action === 'login' ? '登录' : ($action === 'register' ? '注册' : '首页'); ?></h1>
        <?php if ($message): ?>
            <p class="<?php echo $msgType; ?>"><?php echo $message; ?></p>
        <?php endif; ?>

        <?php if ($action === 'login' || $action === 'register'): ?>
            <form method="post">
                <div>
                    <label>用户名:</label>
                    <input type="text" name="username" required>
                </div>
                <div>
                    <label>密码:</label>
                    <input type="password" name="password" required>
                </div>
                <button type="submit"><?php echo $action === 'login' ? '登录' : '注册'; ?></button>
            </form>
            <div>
                <?php echo $action === 'login' ? '还没有账号?<a href="?action=register">去注册</a>' : '已有账号?<a href="?action=login">去登录</a>'; ?>
            </div>
        <?php endif; ?>
    </div>
</body>
</html>
相关推荐
ZHOUPUYU1 小时前
PHP 8.3网关优化:我用JIT将QPS提升300%的真实踩坑录
开发语言·php
寻寻觅觅☆5 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
萧曵 丶5 小时前
Vue 中父子组件之间最常用的业务交互场景
javascript·vue.js·交互
银烛木5 小时前
黑马程序员前端h5+css3
前端·css·css3
m0_607076605 小时前
CSS3 转换,快手前端面试经验,隔壁都馋哭了
前端·面试·css3
听海边涛声5 小时前
CSS3 图片模糊处理
前端·css·css3
IT、木易5 小时前
css3 backdrop-filter 在移动端 Safari 上导致渲染性能急剧下降的优化方案有哪些?
前端·css3·safari
l1t5 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
赶路人儿6 小时前
Jsoniter(java版本)使用介绍
java·开发语言
Amumu121386 小时前
Vue3扩展(二)
前端·javascript·vue.js