目录

第五章-PHP函数

目录

/weixin_miniapp.png

第五章-PHP函数

PHP函数

一,函数的基本概念

函数(Function)是 PHP 中用于封装可重用代码的核心工具。通过函数,可以将复杂逻辑模块化,提高代码的可读性、复用性和可维护性。

一、函数的定义与语法

1. 基本语法

PHP 函数通过 function 关键字定义,语法如下:

function 函数名(参数1, 参数2 = 默认值, ...): 返回类型 {
    // 逻辑代码
    return 值; // 可选
}

示例 :

function add(int $a, int $b = 10): int {
    return $a + $b;
}
echo add(5);      // 输出 15 (5 + 10)
echo add(3, 7);   // 输出 10 (3 + 7)
2. 关键组成部分
  • 参数 :
    • 支持默认值(如 $b = 10 )。
    • 可指定类型(如 int $a ,PHP 7+ 支持标量类型声明)。
  • 返回值 :
    • 使用 return 返回结果,若未指定则默认返回 null 。
    • PHP 7+ 支持返回类型声明(如 : int )。
3. 匿名函数(闭包)

匿名函数没有名称,常用于回调或赋值给变量:

$greet = function($name) {
    echo "Hello, $name!";
};
$greet("Alice"); // 输出:Hello, Alice!
4. 箭头函数(PHP 7.4+)

简化匿名函数语法,自动捕获外部变量:

$multiplier = 2;
$double = fn($x) => $x * $multiplier;
echo $double(5); // 输出:10

二、函数的命名规范

良好的命名规范能显著提升代码可读性。以下是 PHP 函数的常见命名规则:

1. 命名风格
  • 驼峰式(camelCase) :

    function getUserData() { ... }
  • 下划线式(snake_case) (传统风格):

    function get_user_data() { ... }
2. 命名原则
  • 清晰表达功能 :

    函数名应明确描述其作用,如 calculateTotalPrice() 。

  • 使用动词 :

    函数通常表示一个动作,如 createUser() 、 validateEmail() 。

  • 布尔函数 :

    以 is 、 has 、 can 开头,返回布尔值:

    function isValidEmail($email): bool { ... }
3. 避免的命名
  • 无意义名称 :如 doSomething() 、 process() 。
  • 与内置函数冲突 :如 array() 、 echo() 。

三、函数的调用与作用域

1. 调用方式
  • 直接调用:

    echo add(3, 5);
  • 动态调用(可变函数):

    $funcName = "add";
    echo $funcName(3, 5); // 等同于 add(3, 5)
    
2. 变量作用域
  • 局部变量 :函数内部定义的变量仅在函数内有效。

  • 全局变量 :需通过 global 或 $GLOBALS 访问:

    $globalVar = 100;
    function showGlobal() {
        global $globalVar;
        echo $globalVar; // 输出 100
    }

四、最佳实践

  1. 单一职责原则

    一个函数只完成一个任务。

    // 错误示例:混合功能
    function processUser($data) {
        validate($data);
        saveToDatabase($data);
        sendEmail($data);
    }
    
    // 正确示例:拆分功能
    function validateUser($data) { ... }
    function saveUser($data) { ... }
  2. 参数与返回值

    • 参数尽量不超过 3 个,复杂数据可用数组或对象封装。
    • 使用类型声明(PHP 7+)提升代码健壮性。
  3. 错误处理

    • 验证输入参数,避免函数内部崩溃。
    function divide(int $a, int $b): float {
        if ($b === 0) {
            throw new InvalidArgumentException("除数不能为0");
        }
        return $a / $b;
    }

五、总结

核心要点说明
定义语法function 函数名(参数): 返回类型 { ... }
命名规范动词开头,清晰表达功能(如 calculateTotal() )
参数与返回值类型声明、默认值、异常处理
作用域管理局部变量、全局变量、闭包捕获

二,实际参数与形式参数

在 PHP 函数中,**形式参数(形参) 和 实际参数(实参)**是函数参数传递的两个核心概念。它们的区别与联系直接决定了函数如何接收和处理数据。


1. 形式参数(Formal Parameters)

  • 定义 :

    形式参数是函数 定义时声明的参数 ,用于接收外部传入的值,是函数内部的局部变量。

  • 位置 :

    出现在函数声明的小括号中,例如 function sum($a, $b) 中的 $a 和 $b 。

  • 作用 :

    • 作为占位符,定义函数需要接收的数据类型和数量。
    • 仅在函数体内有效,与外部变量无关(除非使用引用传递)。

示例 :

function calculateTotal($price, $quantity) { // $price 和 $quantity 是形式参数
    return $price * $quantity;
}

2. 实际参数(Actual Parameters)

  • 定义 :

    实际参数是函数 调用时传递的具体值或变量 ,用于为形式参数提供实际数据。

  • 位置 :

    出现在函数调用的小括号中,例如 sum(3, 5) 中的 3 和 5 。

  • 作用 :

    • 将外部数据传递给函数。
    • 可以是字面量(如数字、字符串)、变量或表达式。

示例 :

$itemPrice = 100;
$itemCount = 2;

// 调用 calculateTotal 函数,传递实际参数
$total = calculateTotal($itemPrice, $itemCount); 
// $itemPrice 和 $itemCount 是实际参数

3. 关键区别与联系

特性形式参数实际参数
定义位置函数声明时定义函数调用时传递
作用域仅在函数体内有效可以是全局变量或局部变量
数据来源由实际参数赋值来自函数外部
生命周期函数执行时创建,结束后销毁独立于函数存在

4. 参数传递方式

PHP 默认采用 按值传递 ,但也可通过引用传递修改外部变量。

  1. 按值传递 (默认):

    • 形式参数是实际参数的副本,函数内修改不影响外部变量。
    function increment($num) {
        $num++;
        echo "函数内: $num"; // 输出 6
    }
    
    $value = 5;
    increment($value);
    echo "函数外: $value";   // 输出 5(未改变)
    
  2. 按引用传递 :

    • 使用 & 符号,形式参数与实际参数指向同一内存地址,函数内修改会影响外部变量。
    function incrementRef(&$num) {
        $num++;
    }
    
    $value = 5;
    incrementRef($value);
    echo $value; // 输出 6
    

5. 默认参数与可变参数

  1. 默认参数 :

    形式参数可设置默认值,调用时若未传递实参则使用默认值。

    function greet($name = "Guest") {
        echo "Hello, $name!";
    }
    
    greet();          // 输出:Hello, Guest!
    greet("Alice");   // 输出:Hello, Alice!
    
  2. 可变参数(可变长度参数列表) :

    使用 ... 或 func_get_args() 接收任意数量的实参。

    // PHP 5.6+ 使用 ... 语法
    function sum(...$numbers) {
        return array_sum($numbers);
    }
    echo sum(1, 2, 3); // 输出 6
    

6. 类型约束(PHP 7+)

形式参数可指定类型,强制实参必须匹配类型,提升代码健壮性:

function divide(int $a, int $b): float {
    if ($b === 0) {
        throw new InvalidArgumentException("除数不能为0");
    }
    return $a / $b;
}

echo divide(10, 3); // 输出 3.333...
// divide("10", 3); // 类型错误:期望 int,传递了字符串

总结

  • 形式参数 是函数定义的“占位符”,决定函数如何接收数据。
  • 实际参数 是调用函数时传递的具体数据,决定函数处理的内容。
  • 按值传递 与 按引用传递 决定了数据修改是否影响外部变量。
  • 类型约束 和 默认参数 可增强代码的可靠性和灵活性。

三,参数处理

PHP 函数参数处理是编写灵活且健壮代码的核心技能之一。以下是 PHP 中参数处理的主要方式、规则及最佳实践:


1. 参数传递方式

PHP 支持两种参数传递方式:

按值传递(默认)
  • 特点 :函数内部修改参数不会影响外部变量。

  • 定义与使用

    • 语法 :在函数定义时为参数指定默认值,调用时若未传递该参数则使用默认值。

      function greet($name = "Guest") {
          echo "Hello, $name!";
      }
      greet();        // 输出:Hello, Guest!
      greet("Alice"); // 输出:Hello, Alice!
      
  • 规则与限制

    1. 参数顺序 :

      默认参数必须放在非默认参数之后 ,否则会导致语法错误。

      // 正确:默认参数在后
      function example($a, $b = 2, $c = 3) { /* ... */ }
      
      // 错误:非默认参数在默认参数之后
      function wrong($a = 1, $b) { /* ... */ } // 编译错误
      
    2. 灵活调用 :

      PHP 8.0+ 支持 命名参数 ,允许跳过中间参数直接为指定参数赋值。

      example(1, c: 5); // PHP 8.0+:$a=1, $b=2(默认), $c=5
      
按引用传递
  • 特点 :通过 & 符号声明参数,函数内部修改直接影响外部变量。

  • 定义与使用

    • 语法 :在参数前添加 & ,使函数内部修改直接影响外部变量。

      function increment(&$num) {
          $num++;
      }
      
      $value = 5;
      increment($value);
      echo $value; // 输出:6
      
  • 规则与限制

    1. 实参必须为变量 :

      引用传递要求实参必须是已定义的变量,不能是字面量或表达式结果。

      increment(5);       // 错误:Cannot pass literal as reference
      increment($x + 1);  // 错误:表达式结果无法传递
      
    2. 默认值与引用冲突 :

      引用参数无法设置字面量默认值 ,因为引用必须绑定到变量。

      // 错误示例
      function refWithDefault(&$var = 10) { /* ... */ } // 编译错误
      

2. 默认参数值

为参数设置默认值,调用时可选传递:

语法规则
  • 默认参数必须放在参数列表末尾。

  • 正确示例 :

    function greet($name = "Guest", $greeting = "Hello") {
        echo "$greeting, $name!";
    }
    greet(); // 输出:Hello, Guest!
    
  • 错误示例 :

    function errorExample($a = 1, $b) {} // 编译错误:非默认参数在默认参数后
    
PHP 8+ 命名参数

允许跳过中间参数,直接指定参数名赋值:

greet(greeting: "Hi"); // 输出:Hi, Guest!

3. 可变数量参数

处理不确定数量的参数输入:

传统方式(PHP 5.5 及以下)

使用 func_get_args() 获取参数数组:

function sum() {
    $args = func_get_args();
    return array_sum($args);
}
echo sum(1, 2, 3); // 输出 6
可变参数语法(PHP 5.6+)

使用 ... 操作符:

function sum(...$numbers) {
    return array_sum($numbers);
}
echo sum(1, 2, 3); // 输出 6
类型约束可变参数

限制可变参数的类型:

function sumInts(int ...$numbers) {
    return array_sum($numbers);
}
sumInts(1, 2, "3"); // "3" 转换为整数 3

4. 类型声明(PHP 7+)

增强参数和返回值的类型安全:

标量类型约束
  • 支持 int , string , float , bool 等类型。

    function add(int $a, int $b): int {
        return $a + $b;
    }
    echo add(2, 3);   // 输出 5
    echo add("2", 3); // 字符串 "2" 转换为整数 2
    
严格模式

在文件顶部声明 declare(strict_types=1); 强制类型检查:

declare(strict_types=1);
function strictAdd(int $a, int $b): int {
    return $a + $b;
}
strictAdd("2", 3); // 报错:期望 int,传递了字符串

5. 参数解构(PHP 7.1+)

从数组或对象中解构参数:

function printCoordinates([$x, $y]) {
    echo "X: $x, Y: $y";
}
$point = [3, 5];
printCoordinates($point); // 输出:X: 3, Y: 5

6. 最佳实践

  1. 避免滥用引用传递

    仅在需要函数内部修改外部变量时使用引用,否则优先按值传递。

  2. 合理设置默认值

    默认参数应提供合理的后备值,避免 null 陷阱:

    // 错误:默认值 null 可能导致逻辑漏洞
    function logMessage($message = null) {
        if ($message === null) $message = "No message";
        // ...
    }
  3. 优先使用类型声明

    PHP 7+ 的类型约束能显著减少类型错误:

    function safeDivide(int $a, int $b): float {
        if ($b === 0) throw new InvalidArgumentException("除数不能为0");
        return $a / $b;
    }
  4. 命名参数提升可读性

    PHP 8+ 的命名参数使代码更清晰:

    setUser(name: "Alice", age: 25); // 明确参数含义
    

总结

特性说明适用场景
按值传递默认方式,安全无副作用大多数场景
按引用传递需显式声明 & ,直接修改外部变量需要函数内部修改外部数据时
默认参数必须放在参数列表末尾可选参数的函数
可变参数使用 ... 或 func_get_args()处理不确定数量的输入
类型声明强制参数和返回值类型(PHP 7+)提升代码健壮性
命名参数明确参数含义(PHP 8+)跳过可选参数或增强可读性

四,函数体结构

PHP 函数通过 function 关键字定义,其核心由 函数体 和 返回值 组成。合理的函数体设计与返回值处理是编写可维护、高效代码的关键。


一、函数体

函数体是位于 {} 内的代码块,包含函数的核心逻辑。其结构特点如下:

1. 基本语法
function 函数名(参数列表): 返回类型声明 {
    // 函数体逻辑
    return 返回值; // 可选
}
2. 变量作用域
  • 局部变量 :函数内定义的变量仅在函数体内有效。

    function calculate() {
        $localVar = 10; // 局部变量
        echo $localVar; // 有效
    }
    calculate();
    echo $localVar; // 报错:未定义变量
    
  • 全局变量 :需通过 global 或 $GLOBALS 访问。

    $globalVar = 5;
    function showGlobal() {
        global $globalVar;
        echo $globalVar; // 输出 5
    }
3. 函数执行流程
  • 顺序执行 :代码从上到下执行,直到遇到 return 或函数结束。
  • return 的作用 :
    • 终止函数执行,立即返回结果。
    • 未显式 return 时,函数默认返回 null 。

二、返回值处理
1. 基本返回
  • 单值返回 :使用 return 返回单个值。

    function add($a, $b) {
        return $a + $b;
    }
    echo add(3, 5); // 输出 8
    
  • 无返回值 :函数默认返回 null 。

    function logMessage($msg) {
        echo "日志:$msg";
    }
    $result = logMessage("test"); // $result 为 null
    
2. 返回类型声明(PHP 7+)
  • 强制指定返回类型 :避免类型不一致问题。

    function divide(int $a, int $b): float {
        return $a / $b;
    }
    echo divide(10, 3); // 输出 3.333...
    
  • 严格模式 :使用 declare(strict_types=1); 禁用自动类型转换。

    declare(strict_types=1);
    function strictDivide(int $a, int $b): float {
        return $a / $b;
    }
    strictDivide("10", 3); // 报错:参数类型不匹配
    
3. 多返回值模拟

PHP 不支持直接返回多个值,但可通过以下方式实现:

  • 返回数组 :

    function getUserInfo() {
        return ['name' => 'Alice', 'age' => 25];
    }
    $user = getUserInfo();
    echo $user['name']; // Alice
    
  • 返回对象 :

    class User {
        public $name;
        public $age;
    }
    function createUser() {
        $user = new User();
        $user->name = 'Bob';
        $user->age = 30;
        return $user;
    }
    echo createUser()->name; // Bob
    
  • 引用返回(不推荐) :

    function &getReference() {
        static $value = 0;
        $value++;
        return $value;
    }
    $ref = &getReference(); // $ref 是 $value 的引用
    $ref = 10;
    echo getReference(); // 输出 11(原值被修改)
    
4. 返回 void (PHP 7.1+)

明确表示函数无返回值:

function noReturn(): void {
    echo "无返回值";
    // return; 可选,但不能返回任何值
}
noReturn();

三、函数体设计最佳实践
1. 单一职责原则

一个函数只做一件事:

// 错误:混合验证与保存
function processUser($data) {
    if (!validEmail($data['email'])) {
        throw new Exception("邮箱无效");
    }
    saveToDatabase($data);
}

// 正确:拆分职责
function validateUser($data) { /* 验证逻辑 */ }
function saveUser($data) { /* 数据库操作 */ }
2. 错误处理
  • 抛出异常 :遇到不可恢复错误时终止执行。

    function loadFile($path) {
        if (!file_exists($path)) {
            throw new RuntimeException("文件不存在");
        }
        return file_get_contents($path);
    }
  • 返回错误码或 null :

    function findUser($id) {
        // 查询数据库...
        return $user ?? null; // 未找到返回 null
    }
3. 避免副作用

函数应专注于计算或操作,而非修改外部状态:

// 错误:修改全局变量
$counter = 0;
function incrementCounter() {
    global $counter;
    $counter++;
}

// 正确:通过返回值传递状态
function increment($num) {
    return $num + 1;
}
$counter = increment($counter);

四、常见错误与调试
1. 未捕获的返回值
function calculate() {
    // 忘记 return
    $result = 5 + 3;
}
echo calculate(); // 输出 null(而非 8)
2. 类型不匹配
function getNumber(): int {
    return "10"; // PHP 自动转换为 10(严格模式下报错)
}
3. 引用返回陷阱
function &getArrayRef() {
    $arr = [1, 2, 3];
    return $arr; // 返回局部变量的引用(危险!)
}
$ref = &getArrayRef(); // $ref 指向已销毁的数组

五、总结
关键点说明
函数体结构包含局部变量、逻辑代码,通过 return 终止执行并返回结果
返回值设计支持单值、数组、对象,类型声明提升安全性, void 明确无返回值
最佳实践单一职责、错误处理、避免副作用
调试技巧检查 return 遗漏、类型约束、避免无效引用

五,变量作用域

一、局部变量(Local Variables)

定义

在函数内部声明的变量称为 局部变量 ,其作用域仅限于声明它的函数内部。

特点

  1. 作用域限制 :

    只能在函数内部访问,函数外部无法直接访问局部变量。

  2. 生命周期 :

    函数调用时创建,函数执行完毕后销毁。

  3. 独立性 :

    不同函数中的同名局部变量互不影响。

示例

function exampleFunction() {
    $localVar = "I am a local variable";
    echo $localVar; // 输出:I am a local variable
}

exampleFunction();
// echo $localVar; // 报错:Undefined variable(无法访问)

二、全局变量(Global Variables)

定义

在函数外部声明的变量称为 全局变量 ,作用域为当前脚本的全局范围,但默认无法直接在函数内部访问。

访问方式

  1. global 关键字 :

    在函数内部声明一个全局变量,使其在函数内可用。

  2. $GLOBALS 超全局数组 :

    直接通过 $GLOBALS 数组访问或修改全局变量。

示例

$globalVar = "I am global"; // 全局变量

function accessGlobal() {
    global $globalVar;      // 声明为全局变量
    echo $globalVar;        // 输出:I am global
    
    $GLOBALS['globalVar'] = "Modified by GLOBALS"; // 直接修改全局变量
}

accessGlobal();
echo $globalVar; // 输出:Modified by GLOBALS
注意事项
  • 滥用全局变量会导致代码耦合性高、难以调试。
  • 优先通过参数传递和返回值在函数间传递数据。

三、超全局变量(Superglobals)

定义

PHP 预定义的一组特殊全局变量,作用域为 所有代码范围 (包括函数、类内部),无需显式声明即可访问。

常见超全局变量

变量名用途
$_GET获取 URL 查询参数(GET 请求)
$_POST获取表单提交数据(POST 请求)
$_SESSION操作会话数据(需先启动会话)
$_COOKIE读取客户端 Cookie
$_SERVER获取服务器和请求信息
$_FILES获取上传文件信息
$_REQUEST合并 GET、POST、COOKIE 数据
$_ENV读取环境变量

示例

function processForm() {
    $username = $_POST['username'] ?? 'Guest'; // 直接访问超全局变量
    echo "Hello, $username!";
}

// 假设用户提交了 username=Alice
processForm(); // 输出:Hello, Alice!

安全性注意

  • 超全局变量(如 $_GET 、 $_POST )可能包含用户输入,需严格过滤:

    php

    复制

    $cleanInput = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);

四、静态变量(Static Variables)

定义

在函数内部使用 static 关键字声明的变量,其值在函数多次调用之间保留。

特点

  • 生命周期 :脚本执行期间持续存在,但仅在声明它的函数内可访问。
  • 初始化 :仅在第一次函数调用时初始化。

示例

function counter() {
    static $count = 0; // 静态变量
    $count++;
    echo "Count: $count\n";
}

counter(); // 输出:Count: 1
counter(); // 输出:Count: 2
counter(); // 输出:Count: 3

五、闭包(匿名函数)与 use 关键字

定义

匿名函数(闭包)可以捕获外部作用域的变量,但需通过 use 关键字显式声明。

示例

$externalVar = "Hello";

$anonymousFunction = function() use ($externalVar) {
    echo $externalVar; // 输出:Hello
};

$anonymousFunction();

注意事项

  • 默认通过 use 传递的是变量的值(拷贝),若需修改外部变量,需传递引用:

    $num = 1;
    $func = function() use (&$num) {
        $num++;
    };
    $func();
    echo $num; // 输出:2
    

六 , 在函数内访问全局变量

方法一: global 关键字

  • 在函数内部使用 global 声明后,可访问全局变量。

    $a = 1;
    $b = 2;
    
    function sum() {
        global $a, $b;
        $b = $a + $b; // 修改全局变量$b的值
    }
    sum();
    echo $b; // 输出3
    

方法二: $GLOBALS 超全局数组

  • 直接通过 $GLOBALS['varName'] 访问或修改全局变量。

    $x = 10;
    
    function increment() {
        $GLOBALS['x']++;
    }
    increment();
    echo $x; // 输出11
    

七、作用域对比表

变量类型作用域生命周期访问方式
局部变量函数内部函数执行期间直接访问
全局变量脚本全局(函数外)脚本执行结束前global 或 $GLOBALS
超全局变量所有作用域脚本执行结束前直接访问(如 $_POST )
静态变量函数内部脚本执行结束前static 声明
闭包捕获的变量匿名函数内部(通过 use )依赖外部变量作用域显式传递(值或引用)

八、最佳实践

  1. 避免全局变量 :优先使用参数传递和返回值。
  2. 过滤超全局变量 :使用 filter_input() 或 htmlspecialchars() 防止安全漏洞。
  3. 慎用静态变量 :仅在需要跨调用保留状态时使用(如计数器)。
  4. 闭包的变量捕获 :明确使用 use 传递所需变量,避免内存泄漏。

九、常见问题

  1. 函数内部能访问外部同名变量吗?
  • 不能,除非显式声明为 global 或通过 use 传递。
  1. 如何让函数修改全局变量?
  • 使用 global 或 $GLOBALS 。
  1. 静态变量和全局变量的区别?
  • 静态变量仅在函数内可访问,全局变量在整个脚本中可访问。

六,可变函数

在PHP中,可变函数(Variable Functions)允许通过变量名动态调用函数。这一特性提供了代码的灵活性,但需谨慎使用以避免安全隐患。以下是详细解析:


1. 基本概念

可变函数是指将函数名存储为字符串变量,通过变量加括号 $var() 的形式调用函数。PHP会解析变量的值作为函数名,并执行对应的函数。

示例 :

function greet() {
    echo "Hello, World!";
}

$func = 'greet';
$func(); // 输出:Hello, World!

2. 语法与参数传递

  • 调用带参数的函数

    直接向可变函数传递参数,参数需按顺序匹配。

    function add($a, $b) {
        return $a + $b;
    }
    
    $operation = 'add';
    echo $operation(3, 5); // 输出:8
    

3. 动态调用类方法

可变函数可用于调用对象的方法或静态方法,需注意方法的作用域(public/protected/private)。

对象方法调用

class Calculator {
    public function multiply($x, $y) {
        return $x * $y;
    }
}

$obj = new Calculator();
$method = 'multiply';
echo $obj->$method(4, 5); // 输出:20

静态方法调用

class Math {
    public static function square($n) {
        return $n * $n;
    }
}

$staticMethod = 'Math::square';
echo $staticMethod(4); // 输出:16

// 或使用数组形式
$callable = ['Math', 'square'];
echo call_user_func($callable, 4); // 输出:16

4. 安全性与验证

  • 检查函数是否存在

    使用 function_exists() 或 method_exists() 避免调用未定义的函数。

    $functionName = 'unknownFunction';
    
    if (function_exists($functionName)) {
        $functionName();
    } else {
        echo "函数不存在!";
    }
  • 避免用户输入直接作为函数名

    未过滤的用户输入可能导致代码注入。

    // 危险示例(勿用):
    $userInput = $_GET['action'];
    $userInput(); // 若用户传入"exec"等危险函数名,后果严重
    
    // 安全做法:
    $allowed = ['safeAction1', 'safeAction2'];
    if (in_array($userInput, $allowed)) {
        $userInput();
    }

5. 与匿名函数(闭包)结合

可变函数也可调用通过 create_function() 或匿名函数定义的闭包。

$closure = function($name) {
    echo "Hi, $name!";
};

$func = 'closure';
$func('Alice'); // 输出:Hi, Alice!

6. 回调函数中的应用

可变函数常用于需要回调的场景,如 array_map() 、 usort() 等。

function upper($str) {
    return strtoupper($str);
}

$strings = ['apple', 'banana'];
$callback = 'upper';
print_r(array_map($callback, $strings)); // 输出:['APPLE', 'BANANA']

7. 注意事项

  1. 方法可见性

    若尝试调用私有或受保护的方法,会触发错误。

    class Secret {
        private function hidden() {
            echo "Secret!";
        }
    }
    
    $obj = new Secret();
    $method = 'hidden';
    $obj->$method(); // 报错:Cannot access private method
    
  2. 变量解析顺序

    若变量与函数同名,优先调用函数。

    function test() { echo "Function called"; }
    $test = 'test';
    $test(); // 正确:输出"Function called"
    
  3. 性能考量

    动态调用比直接调用稍慢,但在大多数场景下影响可忽略。


8. 典型应用场景

  • 路由分发 :根据URL参数动态调用控制器方法。

    $controller = new UserController();
    $action = $_GET['action'] ?? 'index';
    if (method_exists($controller, $action)) {
        $controller->$action();
    }
  • 插件系统 :动态加载并调用插件函数。

  • 工厂模式 :根据条件创建不同类的实例。


总结

可变函数为PHP提供了强大的动态调用能力,但需遵循以下最佳实践:

  1. 严格验证 :确保调用的函数或方法存在且安全。
  2. 避免直接用户输入 :防止代码注入漏洞。
  3. 明确作用域 :注意类方法的可见性。
  4. 合理使用 :在需要灵活性的场景(如框架、回调)中使用,避免过度复杂化代码。

七,匿名函数

在PHP中,匿名函数(Anonymous Functions),也称为闭包(Closures),是一种没有显式名称的函数,可以直接赋值给变量、作为参数传递或从其他函数返回。它们特别适合需要动态定义行为的场景(如回调、事件处理等)。以下是详细解析:


1. 基本语法

匿名函数通过 function () use (...) { ... } 定义,可捕获外部变量。

示例:

$greet = function ($name) {
    echo "Hello, $name!";
};

$greet("Alice"); // 输出:Hello, Alice!

2. 捕获外部变量

use 关键字

匿名函数默认无法访问外部作用域的变量,需通过 use 显式捕获。

  • 按值捕获 (默认):复制变量当前值。
  • 按引用捕获 ( & ):引用变量,修改会影响外部作用域。

示例:

$prefix = "User: ";

// 按值捕获
$func1 = function ($name) use ($prefix) {
    echo $prefix . $name; // 输出:User: Alice
    $prefix = ""; // 修改不影响外部变量
};
$func1("Alice");
echo $prefix; // 仍为 "User: "

// 按引用捕获
$func2 = function ($name) use (&$prefix) {
    $prefix = "ID: "; // 修改会影响外部变量
    echo $prefix . $name; // 输出:ID: Bob
};
$func2("Bob");
echo $prefix; // 变为 "ID: "

3. 作为参数传递

匿名函数常用于回调场景,如 array_map 、 usort 等。

示例:

$numbers = [1, 2, 3, 4];

// 使用匿名函数作为回调
$squared = array_map(function ($n) {
    return $n * $n;
}, $numbers);

print_r($squared); // 输出:[1, 4, 9, 16]

4. 返回匿名函数

函数可以返回一个匿名函数,闭包会保留其定义时的上下文。

示例:

function createMultiplier($factor) {
    return function ($n) use ($factor) {
        return $n * $factor;
    };
}

$double = createMultiplier(2);
echo $double(5); // 输出:10

5. 与对象结合

绑定闭包到对象

通过 bindTo 方法,可以将闭包绑定到特定对象,访问其私有/受保护成员。

示例:

class User {
    private $name = "Anonymous";
}

$getUserName = function () {
    return $this->name;
};

$user = new User();
// 将闭包绑定到 $user 对象,并赋予访问私有属性的权限
$boundClosure = $getUserName->bindTo($user, $user);
echo $boundClosure(); // 输出:Anonymous

6. 立即执行匿名函数

通过 (function () { ... })(); 语法,匿名函数可以定义后立即执行。

示例:

$result = (function ($a, $b) {
    return $a + $b;
})(3, 5);

echo $result; // 输出:8

7. 静态匿名函数(PHP 8.1+)

PHP 8.1 引入了静态匿名函数,禁止捕获外部变量,提升性能。

示例:

$staticClosure = static function () {
    // 无法使用 use 捕获外部变量
    return "Static closure";
};

8. 实际应用场景

  1. 回调处理

    如事件监听、数组操作的回调。

    $users = ["Alice", "Bob"];
    array_walk($users, function ($name) {
        echo "Processing $name\n";
    });
  2. 延迟执行

    将逻辑封装为闭包,稍后调用。

    $task = function () {
        echo "Task executed at " . date('H:i:s');
    };
    sleep(2);
    $task(); // 2秒后执行
    
  3. 策略模式

    动态选择算法逻辑。

    function calculate($a, $b, $strategy) {
        return $strategy($a, $b);
    }
    
    $addition = function ($x, $y) { return $x + $y; };
    $subtraction = function ($x, $y) { return $x - $y; };
    
    echo calculate(10, 5, $addition);    // 输出:15
    echo calculate(10, 5, $subtraction); // 输出:5
    

9. 注意事项

  1. 变量生命周期

    闭包会延长捕获变量的生命周期,直到闭包被销毁。

    function createClosure() {
        $data = "Sensitive Info";
        return function () use ($data) { /* ... */ };
    }
    
    $closure = createClosure();
    // $data 不会被释放,直到 $closure 销毁
    
  2. 避免循环引用

    若闭包捕获了自身所在对象的引用(如 $this ),会导致内存泄漏。

    class Example {
        public function leak() {
            $closure = function () { 
                // 隐式捕获 $this
                echo $this->prop; 
            };
            return $closure;
        }
    }
    // $closure 持有 $this 的引用,导致对象无法释放
    
  3. 性能优化

    频繁创建闭包可能影响性能,需权衡灵活性与效率。


总结

匿名函数为PHP提供了强大的函数式编程能力,支持:

  • 动态定义行为
  • 封装上下文状态
  • 实现高阶函数(函数作为参数或返回值)

合理使用闭包可以简化代码结构,但需注意:

  • 变量捕获规则 ( use 的作用)
  • 内存管理 (避免循环引用)
  • 安全性 (避免闭包暴露敏感数据)

八,伪类型

在PHP中, 伪类型(Pseudo-types) 并非实际存在的数据类型,而是用于函数参数或返回值的文档化标注,帮助开发者理解函数的行为和预期输入/输出。它们通常出现在官方文档或IDE的类型提示中,但在运行时不会被PHP引擎强制校验。


1. mixed (混合类型)

  • 含义 :参数或返回值可以是任意类型(如 string 、 int 、 array 、 object 等)。

  • 常见场景 :函数接受多种类型输入,或返回值的类型不确定。

  • 示例 :

    /**
     * @param mixed $input 可接受任意类型参数
     * @return mixed 可能返回任意类型
     */
    function processInput($input) {
        if (is_numeric($input)) {
            return $input * 2;
        }
        return strtoupper($input);
    }

2. number (数值类型)

  • 含义 :参数或返回值是整数( int )或浮点数( float )。

  • 常见场景 :数学计算函数。

  • 示例 :

    php

    复制

    /**
     * @param number $a 第一个操作数
     * @param number $b 第二个操作数
     * @return number 计算结果
     */
    function multiply($a, $b) {
        return $a * $b;
    }

3. callback (回调类型)

  • 含义 :参数必须是可调用的结构(如函数名、闭包、对象方法数组等)。

  • PHP 替代类型提示 :PHP 5.4+ 支持 callable 类型提示。

  • 示例 :

    php

    复制

    /**
     * @param callable $callback 合法的回调函数
     */
    function executeCallback(callable $callback) {
        $callback();
    }
    
    // 调用示例
    executeCallback(function() { echo "Hello"; }); // 闭包
    executeCallback('strtoupper');                // 函数名
    executeCallback([$obj, 'method']);            // 对象方法
    

4. array|object (数组或对象)

  • 含义 :参数或返回值可以是数组或对象。

  • PHP 替代方案 :PHP 8.0+ 支持联合类型 array|object 。

  • 示例 :

    /**
     * @param array|object $data 输入数据
     */
    function processData($data) {
        if (is_array($data)) {
            // 处理数组
        } elseif (is_object($data)) {
            // 处理对象
        }
    }

5. void (无返回值)

  • 含义 :函数不返回任何值(或隐式返回 null )。

  • PHP 类型提示 :PHP 7.1+ 支持 void 返回类型声明。

  • 示例 :

    /**
     * @return void
     */
    function logMessage(string $message): void {
        file_put_contents('log.txt', $message, FILE_APPEND);
    }

6. resource (资源类型)

  • 含义 :参数或返回值是PHP资源句柄(如文件句柄、数据库连接等)。

  • 注意 : resource 是PHP实际类型,但在某些文档中可能被归类为伪类型。

  • 示例 :

    /**
     * @param resource $fileHandle 打开的文件句柄
     */
    function closeFile($fileHandle): void {
        fclose($fileHandle);
    }

7. ... (可变参数)

  • 含义 :函数接受任意数量的参数。

  • PHP 语法 :使用 ... 运算符实现可变参数。

  • 示例 :

    /**
     * @param mixed ...$numbers 任意数量的数值参数
     * @return float 平均值
     */
    function average(...$numbers): float {
        $sum = array_sum($numbers);
        return $sum / count($numbers);
    }
    echo average(1, 2, 3); // 输出 2
    

8. iterable (可迭代类型)

  • 含义 :参数或返回值是数组或实现了 Traversable 接口的对象(如生成器)。

  • PHP 类型提示 :PHP 7.1+ 支持 iterable 类型提示。

  • 示例 :

    /**
     * @param iterable $list 可遍历的数据集
     */
    function iterateItems(iterable $list): void {
        foreach ($list as $item) {
            echo $item;
        }
    }

伪类型 vs. 实际类型

伪类型PHP 实际类型/替代方案支持版本
mixed无直接替代,需手动检查类型-
numberint 或 float-
callbackcallable 类型提示PHP 5.4+
`arrayobject`联合类型 `arrayobject`
voidvoid 返回类型声明PHP 7.1+
...可变参数语法 ...$argsPHP 5.6+

最佳实践

  1. 优先使用类型声明 :

    在PHP 7+ 中尽量使用 int 、 string 、 callable 等实际类型提示,代替伪类型文档标注。

  2. 伪类型用于文档补充 :

    当参数或返回值的类型无法用单一类型描述时(如 mixed ),用伪类型在PHPDoc中说明。

  3. 严格验证输入 :

    若使用伪类型(如 mixed ),在函数内部需手动校验参数类型,避免运行时错误。

    function handleMixed($input) {
        if (!is_string($input) && !is_array($input)) {
            throw new InvalidArgumentException("Invalid input type");
        }
    }
  4. 利用IDE支持 :

    PHPDoc中的伪类型(如 @return array|object )能为IDE(如PhpStorm)提供代码提示。


总结

伪类型是PHP类型系统的补充工具,主要用于:

  • 提高代码可读性 :明确函数参数和返回值的预期类型。
  • 兼容旧版本 :在PHP 8.0之前的版本中描述复杂类型(如联合类型)。
  • 灵活标注 :处理无法用单一类型描述的场景。

九,常用系统函数

一、字符串处理函数

1. strlen($string)
  • 作用 :获取字符串长度(字节数,非字符数)。

  • 示例 :

    echo strlen("Hello"); // 输出:5
    
2. mb_strlen($string, $encoding)
  • 作用 :获取多字节字符串的字符数(如中文)。

  • 示例 :

    echo mb_strlen("你好", "UTF-8"); // 输出:2
    
3. substr($string, $start, $length)
  • 作用 :截取字符串的子串。

  • 示例 :

    echo substr("Hello World", 6, 5); // 输出:"World"
    
4. str_replace($search, $replace, $string)
  • 作用 :替换字符串中的内容。

  • 示例 :

    echo str_replace("apple", "orange", "I love apple"); // 输出:"I love orange"
    
5. explode($delimiter, $string, $limit)
  • 作用 :按分隔符将字符串拆分为数组。

  • 示例 :

    $arr = explode(",", "a,b,c,d"); // 结果:["a", "b", "c", "d"]
    
6. implode($glue, $array)
  • 作用 :将数组元素连接为字符串。

  • 示例 :

    echo implode("-", ["2023", "08", "01"]); // 输出:"2023-08-01"
    
7. trim($string, $characters)
  • 作用 :去除字符串两端的空白或指定字符。

  • 示例 :

    echo trim("  Hello  "); // 输出:"Hello"
    
8. strpos($haystack, $needle)
  • 作用 :查找子串首次出现的位置(区分大小写)。

  • 示例 :

    echo strpos("Hello World", "World"); // 输出:6
    
9. strtolower($string) / strtoupper($string)
  • 作用 :转换字符串为全小写或全大写。

  • 示例 :

    echo strtoupper("hello"); // 输出:"HELLO"
    
10. htmlspecialchars($string, $flags)
  • 作用 :转义HTML特殊字符,防止XSS攻击。

  • 示例 :

    echo htmlspecialchars("<script>alert('xss')</script>"); // 输出转义后的字符串
    
11. PHP8新增函数
  • str_contains($haystack, $needle) :检查字符串是否包含子串。

  • str_starts_with($haystack, $needle) :检查字符串是否以某子串开头。

  • str_ends_with($haystack, $needle) :检查字符串是否以某子串结尾。

  • 示例 :

    echo str_contains("Hello World", "World"); // 输出:true
    

二、数组处理函数

1. count($array)
  • 作用 :获取数组元素数量。

  • 示例 :

    echo count([1, 2, 3]); // 输出:3
    
2. array_map($callback, $array)
  • 作用 :对数组每个元素应用回调函数。

  • 示例 :

    $nums = [1, 2, 3];
    $squared = array_map(function($n) { return $n * $n; }, $nums); // 结果:[1, 4, 9]
    
3. array_filter($array, $callback)
  • 作用 :过滤数组中满足条件的元素。

  • 示例 :

    $nums = [1, 2, 3, 4];
    $even = array_filter($nums, function($n) { return $n % 2 == 0; }); // 结果:[2, 4]
    
4. array_merge($array1, $array2)
  • 作用 :合并多个数组。

  • 示例 :

    $arr1 = ["a", "b"]; $arr2 = ["c"];  
    print_r(array_merge($arr1, $arr2)); // 结果:["a", "b", "c"]
    
5. array_key_exists($key, $array)
  • 作用 :检查数组中是否存在指定键名。

  • 示例 :

    $user = ["name" => "Alice"];
    echo array_key_exists("name", $user); // 输出:true
    
6. in_array($value, $array)
  • 作用 :检查值是否存在于数组中。

  • 示例 :

    $fruits = ["apple", "banana"];
    echo in_array("apple", $fruits); // 输出:true
    
7. sort($array) / rsort($array)
  • 作用 :对数组进行升序/降序排序(修改原数组)。

  • 示例 :

    $nums = [3, 1, 2]; sort($nums); // 结果:[1, 2, 3]
    
8. array_unique($array)
  • 作用 :移除数组中的重复值。

  • 示例 :

    $nums = [1, 2, 2, 3];
    print_r(array_unique($nums)); // 结果:[1, 2, 3]
    
9. array_column($array, $column_key)
  • 作用 :提取多维数组中的某一列。

  • 示例 :

    $users = [["id" => 1, "name" => "Alice"], ["id" => 2, "name" => "Bob"]];
    print_r(array_column($users, "name")); // 结果:["Alice", "Bob"]
    
10. PHP8.1新增函数
  • array_is_list($array) :检查数组是否为索引数组(键名从0连续递增)。

  • 示例 :

    echo array_is_list(["a", "b", "c"]); // 输出:true
    echo array_is_list([1 => "a", 2 => "b"]); // 输出:false
    

三、文件系统函数

1. file_get_contents($filename)
  • 作用 :读取文件内容到字符串。

  • 示例 :

    $content = file_get_contents("data.txt");
2. file_put_contents($filename, $data)
  • 作用 :将字符串写入文件。

  • 示例 :

    file_put_contents("log.txt", "New log entry", FILE_APPEND);
3. fopen($filename, $mode) / fclose($handle)
  • 作用 :打开/关闭文件句柄。

  • 示例 :

    $file = fopen("data.csv", "r");
    while ($line = fgets($file)) { echo $line; }
    fclose($file);
4. is_file($path) / is_dir($path)
  • 作用 :检查路径是否为文件或目录。

  • 示例 :

    echo is_file("/path/to/file.txt"); // 输出:true
    
5. mkdir($pathname, $mode)
  • 作用 :创建目录。

  • 示例 :

    mkdir("new_folder", 0755); // 创建权限为755的目录
    
6. unlink($filename)
  • 作用 :删除文件。

  • 示例 :

    unlink("old_file.txt");
7. scandir($directory)
  • 作用 :列出目录中的文件和子目录。

  • 示例 :

    $files = scandir("/path/to/dir");
8. realpath($path)
  • 作用 :返回规范化的绝对路径。

  • 示例 :

    echo realpath("../file.txt"); // 输出完整路径
    

四、日期与时间函数

1. date($format, $timestamp)
  • 作用 :格式化时间戳为日期字符串。

  • 示例 :

    echo date("Y-m-d H:i:s"); // 输出:2023-08-01 14:30:00
    
2. time()
  • 作用 :获取当前时间戳(秒数)。

  • 示例 :

    echo time(); // 输出:1690885800
    
3. strtotime($time_string)
  • 作用 :将日期字符串解析为时间戳。

  • 示例 :

    echo strtotime("next Monday"); // 输出下周一的时间戳
    
4. DateTime 类(面向对象风格)
  • 示例 :

    $date = new DateTime("2023-08-01");
    $date->modify("+1 day");
    echo $date->format("Y-m-d"); // 输出:2023-08-02
    

五、数据库操作(MySQLi)

1. mysqli_connect($host, $user, $password, $database)
  • 作用 :连接MySQL数据库。

  • 示例 :

    $conn = mysqli_connect("localhost", "root", "password", "my_db");
2. mysqli_query($conn, $sql)
  • 作用 :执行SQL查询。

  • 示例 :

    $result = mysqli_query($conn, "SELECT * FROM users");
3. mysqli_fetch_assoc($result)
  • 作用 :从结果集中获取一行作为关联数组。

  • 示例 :

    while ($row = mysqli_fetch_assoc($result)) { echo $row["name"]; }
4. mysqli_prepare($conn, $sql)
  • 作用 :预处理SQL语句(防SQL注入)。

  • 示例 :

    $stmt = mysqli_prepare($conn, "INSERT INTO users (name) VALUES (?)");
    mysqli_stmt_bind_param($stmt, "s", $name);
    mysqli_stmt_execute($stmt);

六、错误处理

1. error_reporting($level)
  • 作用 :设置错误报告级别。

  • 示例 :

    error_reporting(E_ALL);
2. try...catch
  • 作用 :捕获异常。

  • 示例 :

    try {
        // 可能抛出异常的代码
    } catch (Exception $e) {
        echo "Error: " . $e->getMessage();
    }
3. set_error_handler($callback)
  • 作用 :自定义错误处理函数。

  • 示例 :

    set_error_handler(function($errno, $errstr) {
        echo "Error: $errstr";
    });

七、JSON处理

1. json_encode($value, $options)
  • 作用 :将PHP值转换为JSON字符串。

  • 示例 :

    $data = ["name" => "Alice", "age" => 30];
    echo json_encode($data); // 输出:{"name":"Alice","age":30}
    
2. json_decode($json, $assoc)
  • 作用 :解析JSON字符串为PHP对象或数组。

  • 示例 :

    $json = '{"name":"Alice","age":30}';
    $obj = json_decode($json);         // 对象形式
    $arr = json_decode($json, true);   // 数组形式
    

八、数学函数

1. rand($min, $max)
  • 作用 :生成指定范围的随机整数。

  • 示例 :

    echo rand(1, 100); // 输出:42
    
2. round($number, $precision)
  • 作用 :四舍五入到指定小数位。

  • 示例 :

    echo round(3.14159, 2); // 输出:3.14
    
3. ceil($number) / floor($number)
  • 作用 :向上/向下取整。

  • 示例 :

    echo ceil(3.2); // 输出:4
    echo floor(3.9); // 输出:3
    

九、其他常用函数

1. header($header)
  • 作用 :发送HTTP头部信息。

  • 示例 :

    header("Location: https://example.com"); // 重定向
    
2. filter_var($value, $filter)
  • 作用 :过滤变量(如验证邮箱)。

  • 示例 :

    $email = "user@example.com";
    if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
        echo "Valid email";
    }
3. session_start()
  • 作用 :启动会话(Session)。

  • 示例 :

    session_start();
    $_SESSION["user"] = "Alice";

总结

PHP的系统函数覆盖了开发中的核心需求,包括:

  • 字符串/数组操作 :处理数据的基础工具。
  • 文件系统 :读写文件和目录管理。
  • 日期时间 :时间处理与格式化。
  • 数据库 :MySQLi和PDO操作。
  • 错误处理 :调试与异常捕获。
  • JSON :数据序列化与解析。

注意事项 :

  1. 根据PHP版本选择函数(如PHP8新增的字符串函数)。
  2. 操作文件或数据库时注意路径和SQL注入安全。
  3. 使用最新函数(如 password_hash() 替代 md5() 加密)。

PHP项目练习:学生信息管理系统

1.项目结构:

/student_manager
│  index.php         // 首页显示学生列表
│  add.php          // 添加学生页面
│  functions.php    // 公共函数文件
│  config.php       // 配置文件
└─includes/         // 包含文件目录
     header.php     // 头部公共文件
     footer.php     // 底部公共文件

2.config.php(配置文件,数据库信息配置)

<?php
// 学生数据存储文件
define('STUDENT_FILE', 'students.txt');
// 站点标题
define('SITE_TITLE', '学生信息管理系统');
?>

3.functions.php(公共函数文件)

<?php
// 保存学生信息到文件
function saveStudent($data) {
    $students = getStudents();
    $students[] = $data;
    file_put_contents(STUDENT_FILE, json_encode($students));
}

// 获取所有学生信息
function getStudents() {
    if(file_exists(STUDENT_FILE)) {
        $content = file_get_contents(STUDENT_FILE);
        return json_decode($content, true) ?: [];
    }
    return [];
}

// 验证表单输入
function validateInput($input) {
    $input = trim($input);
    return !empty($input);
}
?>

4.includes/header.php(公共头部)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title><?= SITE_TITLE ?></title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .error { color: red; }
    </style>
</head>
<body>
    <h1><?= SITE_TITLE ?></h1>
    <nav>
        <a href="index.php">学生列表</a> |
        <a href="add.php">添加学生</a>
    </nav>
    <hr>

5.includes/footer.php(公共底部)

    <hr>
    <footer>
        <p>&copy; <?= date('Y') ?> 学生信息管理系统</p>
    </footer>
</body>
</html>

6.index.php(首页)

<?php
// 包含配置文件和公共函数
require_once 'config.php';
require_once 'functions.php';

// 包含头部
include 'includes/header.php';

// 获取所有学生信息
$students = getStudents();
?>

<h2>学生列表</h2>

<?php if (!empty($students)) : ?>
    <table>
        <tr>
            <th>学号</th>
            <th>姓名</th>
            <th>专业</th>
            <th>年级</th>
        </tr>
        <?php foreach ($students as $student) : ?>
        <tr>
            <td><?= htmlspecialchars($student['id']) ?></td>
            <td><?= htmlspecialchars($student['name']) ?></td>
            <td><?= htmlspecialchars($student['major']) ?></td>
            <td><?= htmlspecialchars($student['grade']) ?></td>
        </tr>
        <?php endforeach; ?>
    </table>
<?php else : ?>
    <p>暂无学生信息</p>
<?php endif; ?>

<?php include 'includes/footer.php'; ?>

7.add.php(添加学生页面)

<?php
require_once 'config.php';
require_once 'functions.php';

$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 获取并验证表单数据
    $id = $_POST['id'] ?? '';
    $name = $_POST['name'] ?? '';
    $major = $_POST['major'] ?? '';
    $grade = $_POST['grade'] ?? '';
    
    if (validateInput($id) && validateInput($name)) {
        // 保存学生信息
        saveStudent([
            'id' => $id,
            'name' => $name,
            'major' => $major,
            'grade' => $grade
        ]);
        
        // 重定向到首页
        header('Location: index.php');
        exit;
    } else {
        $error = "学号和姓名不能为空!";
    }
}

include 'includes/header.php';
?>

<h2>添加新学生</h2>

<?php if ($error) : ?>
    <div class="error"><?= $error ?></div>
<?php endif; ?>

<form method="post">
    <p>
        <label>学号:</label>
        <input type="text" name="id" required>
    </p>
    <p>
        <label>姓名:</label>
        <input type="text" name="name" required>
    </p>
    <p>
        <label>专业:</label>
        <input type="text" name="major">
    </p>
    <p>
        <label>年级:</label>
        <input type="text" name="grade">
    </p>
    <p>
        <button type="submit">添加学生</button>
    </p>
</form>

<?php include 'includes/footer.php'; ?>

总结

这个项目实现了以下功能 :

  1. 使用文件包含(include)实现了公共头部和底部
  2. 使用自定义函数进行数据验证和文件操作
  3. 使用基本语法(条件判断、循环、表单处理等)
  4. 使用文件存储代替数据库(students.txt)
  5. 实现了学生信息的添加和显示功能

主要知识点应用 :

  • 文件包含:通过include语句实现页面模块化
  • 函数:自定义了saveStudent(), getStudents(), validateInput()等函数
  • 基本语法:使用了if/else条件判断、foreach循环、表单处理等
  • 超全局变量:POST、_SERVER的使用
  • 文件操作:file_put_contents和file_get_contents的使用
  • JSON数据格式的编码和解码

学生可以在此基础上扩展以下功能 :

  1. 编辑学生信息
  2. 删除学生信息
  3. 添加更多字段(如联系方式、成绩等)
  4. 增加分页功能
  5. 添加搜索功能
  6. 增加用户登录验证功能

/weixin_miniapp.png