PHP 函数
函数是将一段可复用代码封装起来的机制,通过函数名调用即可执行。良好的函数设计是写出高质量代码的关键——每个函数应该只做一件事,并且做好。PHP 内置了数千个函数,同时支持自定义函数,满足各种开发需求。
函数的核心价值在于代码复用和逻辑封装。将重复的代码提取为函数,不仅减少了代码量,还使得修改更容易——只需改一处,所有调用点都会生效。
定义与调用函数
PHP 使用 function 关键字定义函数:
function greet(string $name): string { return "你好,$name!欢迎学习 PHP。"; }getUserNameecho greet("张三"); // 你好,张三!欢迎学习 PHP。 echo greet("李四"); // 你好,李四!欢迎学习 PHP。 ``
PHP 函数名不区分大小写,但按照惯例应使用小驼峰命名法(
)或下划线命名法(get_user_name)。`参数与默认值
函数参数可以设置默认值,调用时如果不传该参数则使用默认值:
php function createUser( string $name, int $age = 18, string $role = 'user', bool $active = true ): string { $status = $active ? '启用' : '禁用'; return "$name($age 岁)角色:$role,状态:$status"; }`echo createUser("张三"); // 张三(18 岁)角色:user,状态:启用 echo createUser("李四", 25); // 李四(25 岁)角色:user,状态:启用 echo createUser("王五", 30, "admin"); // 王五(30 岁)角色:admin,状态:启用
// PHP 8.0+ 命名参数:可以跳过中间参数 echo createUser("赵六", role: "editor"); // 赵六(18 岁)角色:editor,状态:启用
`注意:有默认值的参数必须放在没有默认值的参数后面。
类型声明
PHP 7+ 支持参数和返回值的类型声明,PHP 8 进一步增强了类型系统:
php // 基本类型声明 function add(int $a, int $b): int { return $a + $b; }`// 联合类型(PHP 8.0+) function formatId(int|string $id): string { return (string)$id; }
// 可空类型 function findUser(?int $id): ?array { if ($id === null) return null; return ['id' => $id, 'name' => '张三']; }
// void 返回类型:函数不返回值 function logMessage(string $msg): void { file_put_contents('app.log', $msg . "\n", FILE_APPEND); // 不能有 return 语句(或只有空 return) }
// never 返回类型(PHP 8.1+):函数永远不正常返回 function redirect(string $url): never { header("Location: $url"); exit; }
...可变参数
使用
运算符接收任意数量的参数:`php function sum(int ...$nums): int { return array_sum($nums); }`echo sum(1, 2, 3); // 6 echo sum(1, 2, 3, 4, 5); // 15
// 混合固定参数和可变参数 function buildQuery(string $table, string ...$fields): string { $cols = implode(', ', $fields); return "SELECT $cols FROM $table"; }
echo buildQuery('users', 'id', 'name', 'email'); // SELECT id, name, email FROM users
// 展开数组作为参数 $numbers = [1, 2, 3, 4, 5]; echo sum(...$numbers); // 15
&引用传参
默认情况下,PHP 函数参数是值传递(传入副本)。使用
可以传递引用,直接修改原变量:`php function addSuffix(string &$str, string $suffix): void { $str .= $suffix; }`$title = "PHP 教程"; addSuffix($title, " - 完整版"); echo $title; // PHP 教程 - 完整版(原变量被修改)
// 对比值传递 function addSuffixByValue(string $str, string $suffix): string { return $str . $suffix; } $title2 = "PHP 教程"; $result = addSuffixByValue($title2, " - 完整版"); echo $title2; // PHP 教程(原变量不变) echo $result; // PHP 教程 - 完整版
`匿名函数(闭包)
匿名函数没有函数名,可以赋值给变量或作为参数传递:
php // 赋值给变量 $multiply = function(int $a, int $b): int { return $a * $b; }; echo $multiply(3, 4); // 12`// 作为回调函数 $numbers = [3, 1, 4, 1, 5, 9, 2, 6]; usort($numbers, function($a, $b) { return $a - $b; }); print_r($numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
// 使用 use 捕获外部变量 $prefix = "用户:"; $format = function(string $name) use ($prefix): string { return $prefix . $name; }; echo $format("张三"); // 用户:张三
// 捕获引用(修改外部变量) $count = 0; $increment = function() use (&$count): void { $count++; }; $increment(); $increment(); echo $count; // 2
`箭头函数(PHP 7.4+)
箭头函数是匿名函数的简写形式,自动捕获外部变量,适合简单的单行函数:
php // 基本语法:fn(参数) => 表达式 $double = fn($n) => $n * 2; echo $double(5); // 10`// 自动捕获外部变量(不需要 use) $tax = 0.1; $withTax = fn($price) => $price * (1 + $tax); echo $withTax(100); // 110
// 在数组函数中使用 $prices = [100, 200, 300, 400, 500]; $discounted = array_map(fn($p) => $p * 0.8, $prices); $expensive = array_filter($prices, fn($p) => $p > 250);
`递归函数
函数调用自身称为递归,适合处理树形结构、分治算法等问题:
php // 阶乘 function factorial(int $n): int { if ($n <= 1) return 1; return $n * factorial($n - 1); } echo factorial(5); // 120(5×4×3×2×1)// 斐波那契数列 function fibonacci(int $n): int { if ($n <= 1) return $n; return fibonacci($n - 1) + fibonacci($n - 2); }
// 遍历目录树 function scanDirectory(string $dir, int $depth = 0): void { $items = scandir($dir); foreach ($items as $item) { if ($item === '.' || $item === '..') continue; echo str_repeat(' ', $depth) . $item . "\n"; $path = $dir . '/' . $item; if (is_dir($path)) { scanDirectory($path, $depth + 1); } } }
常用内置函数速查
| 类别 | 函数 | 说明 |
|---|---|---|
| 数学 | abs($n) | 绝对值 |
| 数学 | ceil($n) | 向上取整 |
| 数学 | floor($n) | 向下取整 |
| 数学 | round($n, $p) | 四舍五入 |
| 数学 | rand($min, $max) | 随机整数 |
| 数学 | max(...$values) | 最大值 |
| 数学 | min(...$values) | 最小值 |
| 字符串 | strlen($s) | 字节长度 |
| 字符串 | mb_strlen($s) | 字符长度(支持中文) |
| 字符串 | str_replace($s,$r,$h) | 替换字符串 |
| 字符串 | explode($d, $s) | 分割字符串 |
| 字符串 | implode($d, $a) | 合并数组为字符串 |
| 数组 | count($a) | 数组长度 |
| 数组 | array_map($fn, $a) | 映射处理 |
| 数组 | array_filter($a, $fn) | 过滤数组 |
| 日期 | date($fmt) | 格式化当前时间 |
| 日期 | time() | 当前时间戳 |
| 类型 | isset($v) | 变量是否存在且非null |
| 类型 | empty($v) | 变量是否为空 |
| 类型 | is_array($v) | 是否为数组 |
常见问题
Q:PHP 函数可以在定义之前调用吗? A:可以,PHP 在执行前会先扫描所有函数定义。但匿名函数赋值给变量的情况除外,变量必须先赋值才能调用。
Q:函数参数太多怎么办? A:当参数超过 3-4 个时,建议将参数封装成数组或对象传入。PHP 8 的命名参数也可以改善多参数函数的调用体验。
Q:匿名函数和箭头函数如何选择? A:单行表达式优先用箭头函数(更简洁,自动捕获变量);需要多行逻辑、或需要用 use` 控制捕获范围时用匿名函数。
Q:递归函数有什么风险? A:递归如果没有正确的终止条件,会导致无限递归,最终耗尽内存或触发 PHP 的最大嵌套深度限制(默认约 500 层)。使用递归时务必确保有明确的终止条件,并考虑用迭代替代深层递归。