第4章:函数

函数是编程中最重要的概念之一,它让我们能够将代码组织成可重用的模块。通过函数,我们可以将复杂的问题分解成更小的、可管理的部分,提高代码的可读性、可维护性和重用性。

学习目标

完成本章学习后,你将能够:

  • 理解函数的概念和作用
  • 掌握函数的定义和调用方法
  • 学会使用参数传递数据
  • 理解返回值的概念和使用
  • 掌握变量作用域的规则
  • 了解PHP内置函数的使用
  • 能够编写可重用的函数模块

本章目录

什么是函数?

函数是一段可重用的代码块,它执行特定的任务。函数可以:

  • 接收输入数据(参数)
  • 处理数据
  • 返回结果(返回值)
  • 被多次调用

函数的优势

  1. 代码重用:一次编写,多处使用
  2. 模块化:将复杂问题分解成小模块
  3. 易维护:修改函数代码,所有调用处都受益
  4. 提高可读性:函数名描述功能,代码更清晰
  5. 便于测试:可以单独测试每个函数

函数的基本结构

function 函数名(参数1, 参数2, ...) {
    // 函数体:执行的代码
    return 返回值; // 可选
}

实际应用示例

让我们通过一个完整的学生管理系统来了解函数的实际应用:

<?php
    // 学生管理系统示例 - 展示函数的实际应用

    // ============================================================================
    // 学生数据管理函数
    // ============================================================================

    // 添加学生
    function addStudent(&$students, $name, $age, $grade, $email = '') {
        // 验证输入数据
        if (empty($name) || $age <= 0 || $grade < 1 || $grade > 12) {
            return [
                'success' => false,
                'message' => '学生信息不完整或无效'
            ];
        }

        // 检查学生是否已存在
        foreach ($students as $student) {
            if ($student['name'] === $name) {
                return [
                    'success' => false,
                    'message' => '学生已存在'
                ];
            }
        }

        // 创建新学生记录
        $newStudent = [
            'id' => generateStudentId($students),
            'name' => $name,
            'age' => $age,
            'grade' => $grade,
            'email' => $email,
            'created_at' => date('Y-m-d H:i:s'),
            'status' => 'active'
        ];

        // 添加到学生数组
        $students[] = $newStudent;

        return [
            'success' => true,
            'message' => '学生添加成功',
            'student' => $newStudent
        ];
    }

    // 生成学生ID
    function generateStudentId($students) {
        if (empty($students)) {
            return 'STU001';
        }

        $maxId = 0;
        foreach ($students as $student) {
            $idNumber = intval(substr($student['id'], 3));
            if ($idNumber > $maxId) {
                $maxId = $idNumber;
            }
        }

        return 'STU' . str_pad($maxId + 1, 3, '0', STR_PAD_LEFT);
    }

    // 查找学生
    function findStudent($students, $searchTerm, $searchType = 'name') {
        $results = [];
        $searchTerm = strtolower($searchTerm);

        foreach ($students as $student) {
            switch ($searchType) {
                case 'name':
                    if (strpos(strtolower($student['name']), $searchTerm) !== false) {
                        $results[] = $student;
                    }
                    break;
                case 'id':
                    if (strtolower($student['id']) === $searchTerm) {
                        return [$student]; // ID查找唯一,直接返回
                    }
                    break;
                case 'grade':
                    if ($student['grade'] == $searchTerm) {
                        $results[] = $student;
                    }
                    break;
            }
        }

        return $results;
    }

    // 删除学生
    function deleteStudent(&$students, $studentId) {
        $found = false;
        foreach ($students as $index => $student) {
            if ($student['id'] === $studentId) {
                array_splice($students, $index, 1);
                $found = true;
                break;
            }
        }

        return $found ?
            ['success' => true, 'message' => '学生删除成功'] :
            ['success' => false, 'message' => '学生不存在'];
    }

    // 更新学生信息
    function updateStudent(&$students, $studentId, $updateData) {
        foreach ($students as &$student) {
            if ($student['id'] === $studentId) {
                // 只更新允许的字段
                $allowedFields = ['name', 'age', 'grade', 'email', 'status'];
                foreach ($allowedFields as $field) {
                    if (isset($updateData[$field])) {
                        $student[$field] = $updateData[$field];
                    }
                }
                $student['updated_at'] = date('Y-m-d H:i:s');

                return [
                    'success' => true,
                    'message' => '学生信息更新成功',
                    'student' => $student
                ];
            }
        }

        return ['success' => false, 'message' => '学生不存在'];
    }

    // ============================================================================
    // 数据统计和分析函数
    // ============================================================================

    // 计算学生总数
    function getTotalStudents($students) {
        return count($students);
    }

    // 按年级统计学生数量
    function getStudentsByGrade($students) {
        $gradeStats = [];

        foreach ($students as $student) {
            $grade = $student['grade'];
            if (!isset($gradeStats[$grade])) {
                $gradeStats[$grade] = 0;
            }
            $gradeStats[$grade]++;
        }

        ksort($gradeStats); // 按年级排序
        return $gradeStats;
    }

    // 计算平均年龄
    function getAverageAge($students) {
        if (empty($students)) {
            return 0;
        }

        $totalAge = 0;
        foreach ($students as $student) {
            $totalAge += $student['age'];
        }

        return round($totalAge / count($students), 1);
    }

    // 获取年龄段分布
    function getAgeDistribution($students) {
        $ageGroups = [
            '6-10岁' => 0,
            '11-15岁' => 0,
            '16-18岁' => 0,
            '18岁以上' => 0
        ];

        foreach ($students as $student) {
            $age = $student['age'];
            if ($age <= 10) {
                $ageGroups['6-10岁']++;
            } elseif ($age <= 15) {
                $ageGroups['11-15岁']++;
            } elseif ($age <= 18) {
                $ageGroups['16-18岁']++;
            } else {
                $ageGroups['18岁以上']++;
            }
        }

        return $ageGroups;
    }

    // ============================================================================
    // 数据展示和格式化函数
    // ============================================================================

    // 显示学生列表
    function displayStudentList($students) {
        if (empty($students)) {
            echo "<p>暂无学生数据</p>";
            return;
        }

        echo "<table border='1' style='border-collapse: collapse; width: 100%;'>";
        echo "<tr style='background-color: #f2f2f2;'>";
        echo "<th>ID</th><th>姓名</th><th>年龄</th><th>年级</th><th>邮箱</th><th>状态</th><th>操作</th>";
        echo "</tr>";

        foreach ($students as $student) {
            $statusColor = $student['status'] === 'active' ? 'green' : 'red';
            $statusText = $student['status'] === 'active' ? '在读' : '离校';

            echo "<tr>";
            echo "<td>{$student['id']}</td>";
            echo "<td>{$student['name']}</td>";
            echo "<td>{$student['age']}</td>";
            echo "<td>{$student['grade']}年级</td>";
            echo "<td>" . ($student['email'] ?: '未填写') . "</td>";
            echo "<td style='color: {$statusColor}'>{$statusText}</td>";
            echo "<td><button onclick='editStudent(\"{$student['id']}\")'>编辑</button> ";
            echo "<button onclick='deleteStudent(\"{$student['id']}\")'>删除</button></td>";
            echo "</tr>";
        }

        echo "</table>";
    }

    // 显示统计信息
    function displayStatistics($students) {
        $totalStudents = getTotalStudents($students);
        $averageAge = getAverageAge($students);
        $gradeStats = getStudentsByGrade($students);
        $ageDistribution = getAgeDistribution($students);

        echo "<h3>统计信息</h3>";
        echo "<div style='display: flex; gap: 20px;'>";

        // 基本统计卡片
        echo "<div style='border: 1px solid #ddd; padding: 15px; border-radius: 5px;'>";
        echo "<h4>基本信息</h4>";
        echo "<p>学生总数: <strong>{$totalStudents}</strong></p>";
        echo "<p>平均年龄: <strong>{$averageAge}岁</strong></p>";
        echo "</div>";

        // 年级分布
        echo "<div style='border: 1px solid #ddd; padding: 15px; border-radius: 5px;'>";
        echo "<h4>年级分布</h4>";
        foreach ($gradeStats as $grade => $count) {
            echo "<p>{$grade}年级: <strong>{$count}人</strong></p>";
        }
        echo "</div>";

        // 年龄分布
        echo "<div style='border: 1px solid #ddd; padding: 15px; border-radius: 5px;'>";
        echo "<h4>年龄分布</h4>";
        foreach ($ageDistribution as $group => $count) {
            echo "<p>{$group}: <strong>{$count}人</strong></p>";
        }
        echo "</div>";

        echo "</div>";
    }

    // 格式化学生信息
    function formatStudentInfo($student) {
        return sprintf(
            "ID: %s | 姓名: %s | 年龄: %d | 年级: %d年级 | 状态: %s",
            $student['id'],
            $student['name'],
            $student['age'],
            $student['grade'],
            $student['status'] === 'active' ? '在读' : '离校'
        );
    }

    // ============================================================================
    // 数据验证函数
    // ============================================================================

    // 验证学生数据
    function validateStudentData($data) {
        $errors = [];

        // 验证姓名
        if (empty($data['name'])) {
            $errors[] = '姓名不能为空';
        } elseif (strlen($data['name']) < 2) {
            $errors[] = '姓名长度至少2个字符';
        }

        // 验证年龄
        if (!isset($data['age'])) {
            $errors[] = '年龄不能为空';
        } elseif (!is_numeric($data['age']) || $data['age'] < 6 || $data['age'] > 25) {
            $errors[] = '年龄必须在6-25岁之间';
        }

        // 验证年级
        if (!isset($data['grade'])) {
            $errors[] = '年级不能为空';
        } elseif (!is_numeric($data['grade']) || $data['grade'] < 1 || $data['grade'] > 12) {
            $errors[] = '年级必须在1-12年级之间';
        }

        // 验证邮箱(可选)
        if (!empty($data['email']) && !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
            $errors[] = '邮箱格式不正确';
        }

        return $errors;
    }

    // ============================================================================
    // 导入导出函数
    // ============================================================================

    // 导出学生数据到CSV
    function exportToCSV($students, $filename = 'students.csv') {
        if (empty($students)) {
            return ['success' => false, 'message' => '没有数据可导出'];
        }

        $csv = "ID,姓名,年龄,年级,邮箱,状态,创建时间\n";

        foreach ($students as $student) {
            $statusText = $student['status'] === 'active' ? '在读' : '离校';
            $csv .= sprintf(
                "%s,%s,%d,%d,%s,%s,%s\n",
                $student['id'],
                $student['name'],
                $student['age'],
                $student['grade'],
                $student['email'],
                $statusText,
                $student['created_at']
            );
        }

        // 设置下载头
        header('Content-Type: text/csv');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        echo $csv;

        return ['success' => true, 'message' => '导出成功'];
    }

    // ============================================================================
    // 演示使用
    // ============================================================================

    // 初始化学生数组
    $students = [];

    echo "<h1>学生管理系统 - 函数应用示例</h1>";

    // 添加一些测试学生
    $result1 = addStudent($students, "张三", 15, 9, "zhangsan@email.com");
    $result2 = addStudent($students, "李四", 14, 8, "lisi@email.com");
    $result3 = addStudent($students, "王五", 16, 10);
    $result4 = addStudent($students, "赵六", 13, 7, "zhaoliu@email.com");

    // 显示添加结果
    echo "<h2>添加学生结果</h2>";
    echo "<p>" . $result1['message'] . "</p>";
    echo "<p>" . $result2['message'] . "</p>";
    echo "<p>" . $result3['message'] . "</p>";
    echo "<p>" . $result4['message'] . "</p>";

    // 显示学生列表
    echo "<h2>学生列表</h2>";
    displayStudentList($students);

    // 显示统计信息
    displayStatistics($students);

    // 搜索示例
    echo "<h2>搜索示例</h2>";
    $searchResults = findStudent($students, "张");
    if (!empty($searchResults)) {
        echo "<p>搜索结果:</p>";
        foreach ($searchResults as $student) {
            echo "<p>" . formatStudentInfo($student) . "</p>";
        }
    }

    // 更新示例
    echo "<h2>更新学生信息</h2>";
    $updateResult = updateStudent($students, "STU001", ['age' => 16, 'email' => 'zhangsan_new@email.com']);
    echo "<p>" . $updateResult['message'] . "</p>";

    // 数据验证示例
    echo "<h2>数据验证示例</h2>";
    $testData = [
        'name' => '',
        'age' => 5,
        'grade' => 13,
        'email' => 'invalid-email'
    ];
    $validationErrors = validateStudentData($testData);
    if (!empty($validationErrors)) {
        echo "<p style='color: red;'>验证错误:</p>";
        foreach ($validationErrors as $error) {
            echo "<p>• {$error}</p>";
        }
    }

    echo "<hr>";
    echo "<h3>函数调用总结:</h3>";
    echo "<ul>";
    echo "<li>addStudent() - 添加学生</li>";
    echo "<li>findStudent() - 查找学生</li>";
    echo "<li>updateStudent() - 更新学生信息</li>";
    echo "<li>getTotalStudents() - 获取学生总数</li>";
    echo "<li>getAverageAge() - 计算平均年龄</li>";
    echo "<li>getStudentsByGrade() - 按年级统计</li>";
    echo "<li>displayStudentList() - 显示学生列表</li>";
    echo "<li>validateStudentData() - 验证数据</li>";
    echo "<li>formatStudentInfo() - 格式化信息</li>";
    echo "<li>exportToCSV() - 导出数据</li>";
    echo "</ul>";
?>

函数的分类

1. 内置函数

PHP提供了大量的内置函数,如:

  • echo() - 输出内容
  • count() - 计算数组元素数量
  • date() - 格式化日期时间
  • strlen() - 获取字符串长度

2. 用户自定义函数

由开发者根据需求创建的函数,如上面的学生管理函数。

3. 匿名函数(闭包)

没有名称的函数,通常用于回调函数:

$students = array_filter($students, function($student) {
    return $student['age'] > 15;
});

学习建议

1. 从简单开始

  • 先理解函数的基本概念
  • 编写简单的单参数函数
  • 逐步增加复杂度

2. 多练习

  • 为常用功能编写函数
  • 练习参数传递和返回值
  • 理解作用域的概念

3. 遵循最佳实践

  • 给函数起有意义的名称
  • 保持函数简洁,单一职责
  • 添加适当的注释
  • 验证输入参数

4. 学习内置函数

  • 熟悉常用的内置函数
  • 查阅官方文档
  • 了解不同函数的使用场景

章节导航

接下来我们将深入学习:

  1. 函数定义与调用:学习如何创建和使用函数
  2. 参数传递:掌握各种参数传递方式
  3. 返回值:理解函数的返回机制
  4. 变量作用域:了解变量的作用范围
  5. 内置函数:探索PHP强大的函数库

每个章节都包含详细的语法说明、丰富的示例代码和实际应用案例,帮助你全面掌握PHP函数编程。


准备好了吗? 函数是编程的核心概念,掌握好函数将大大提高你的编程能力和代码质量!让我们开始深入学习PHP函数的各个知识点。