简介:这是一份面向PHP开发者和学习者的函数速查手册,以PDF电子书形式整理PHP常用内置函数,适合在日常编码、备考复习或课堂教学中随时查阅。内容按功能模块归类,覆盖Apache服务器函数、数组函数、日历函数等主要板块。Apache部分提供请求标头获取、虚拟请求执行等操作说明;数组部分收录了从array()初始化、count()计数、sort()排序到current()、next()等指针遍历的常用方法,并包含用户自定义回调排序;日历部分则涵盖不同历法间的转换函数。每个函数均配有原型与功能说明,便于对照实践。资源仅封装为1个PDF文档,整体体积181KB,轻量易携带,可离线阅读;目前已有148人学习浏览。对希望系统梳理PHP函数体系、减少重复查阅官方文档时间的读者而言,这是一份简洁实用的案头参考。
1. 编码久了,你会发现真正难背的不是语法而是函数签名
晚上十点还在追一个线上 bug:某段老代码把preg_split的第三参数写成了反引用,正则拆分结果少了一截,半小时没看出名堂。最后翻开摘录手册才确认,这个函数的第三个参数是$limit,和explode的第三参数语义并不完全一致。类似场景多了之后你会明白,《PHP函数大全.pdf》这种文件存在的价值,不在于它比官方手册多知道几条知识,而在于它把那些“记得名字、不记得参数顺序”的函数整理成能快速扫视的一页页提要。它适合两类人:刚接触 PHP 不久的人需要一张全貌地图来建立函数认知,写了很多年的老手则把它当作重构时快速核对参数的索引。脑子记不住的东西,交给一本随时能翻的文件去记,效率更高。
2. 读懂 PHP 函数签名:参数顺序、返回值与调用前检查
2.1 先看签名:参数顺序比函数名更能决定用法
不同编程背景的人拿到《PHP函数大全.pdf》时,第一眼应该看的是函数签名那一行,而不是函数名下面的示例。因为 PHP 内置函数来自 C 时代的积累,参数顺序有不一致的历史包袱:比如array_map第一个参数是回调,第二个才是数组;而array_filter第一个参数是数组,第二个是回调。如果不看签名,仅凭名字记忆,组合使用数组函数时就容易写反。
<?php // array_map: 回调在前,数组在后 $upper = array_map('strtoupper', ['php', 'function']); // array_filter: 数组在前,回调在后 $filtered = array_filter( ['php', '', 'null', '0'], fn($v) => $v !== '' ); // 从签名去理解不是“背”,而是形成肌肉记忆 // array_map(callable|null $callback, array $array, array ...$arrays): array // array_filter(array $array, callable|null $callback = null, int $mode = 0): array第一段代码里,array_map的回调放在首参,意味着它可以接受不固定数量的数组参数,回调决定怎么合并这些数组。array_filter则相反,它只是过滤,所以数组必须先出现,回调是可选的。读 PDF 时不要只看到“常用示例”,建议按签名去区分这类“回调和数组谁在前”的细节。签名里的?表示可空类型,比如array_map的回调允许传null,这时它会把多个数组合并成键值对结构,很多从没仔细看手册的人在这里踩坑。
另外,PHP 手册的签名里会写清楚返回类型,比如array_map返回array,array_filter也返回array,但sort系列返回bool。凡是排序、指针移动类的函数,操作结果都出现在参数而不是返回值上,这个规律在数组和文件函数中反复出现,读 PDF 时最先要记住的就是这一类“反直觉函数”清单。
2.2 引用传递与返回值:写错方向就静默丢数据
排查一个常见 Bug 时你会发现,sort这类函数成功返回true,但排好序的内容跑到参数数组里去了。这是 PHP 函数设计中最容易让新人误解的一点。理论上说,函数可以修改调用者传来的变量,只要参数列表里出现&$var这种引用标记。
<?php // 引用传递:函数内部对数组的修改会外溢 function add_prefix(array &$items, string $prefix): void { foreach ($items as $k => $v) { $items[$k] = $prefix . $v; } } $list = ['a', 'b']; add_prefix($list, 'key_'); print_r($list); // 期望: ['key_a', 'key_b']习惯上我们更愿意让函数返回新数组,而不是修改原数组,但sort、rsort、shuffle、reset这一批历史函数就是破坏性的。你在自己的项目里封装函数时,应该尽量避免再定义带引用的接口,除非确实要做原地修改。好处在于:调用方读代码时,看到没有&的参数,就能放心认为原变量不会变。
读取 PDF 时遇到这类函数,我会额外标注一个“返回值无意义”的记号,因为实际逻辑在参数里。在 PHP 8 中,引用传递参数仍然合法,但如果在strict_types下试图给引用参数传入一个字面量,会直接抛TypeError。这类问题不是语法错误,而是运行期错误,经常出现在参数数组为空的边缘场景,初查时极难定位。
2.3 调用前检查:function_exists、扩展加载与反射
PHP 是个版本分裂严重的生态。你在服务器上写mb_strlen,但对方的 PHP 版本没有编译mbstring扩展,就只会得到一个Call to undefined function的致命错误。所以做通用的开源工具或要分发的代码时,调用前先检查是否存在该函数,是常见的稳妥姿势。
<?php // 版本与扩展兼容性检查 if (function_exists('mb_strlen')) { echo mb_strlen('中文'); } else { echo strlen('中文'); } // 拿到当前进程里全部内置函数清单 $internalFunctions = get_defined_functions()['internal']; echo in_array('imagepng', $internalFunctions, true) ? 'GD OK' : 'GD missing';function_exists返回的是一个布尔判断,它可以避免由缺失扩展引起的直接崩溃。get_defined_functions()返回的是数组,包含internal和user两个键,前者是 PHP 内核与扩展提供的函数,后者是你当前脚本里自定义的函数。这个函数在生成《PHP函数大全.pdf》时也很有用,后面会再提到。更深一级的做法是用反射读取参数细节:
<?php $ref = new ReflectionFunction('array_map'); echo $ref->getNumberOfParameters(); // 参数总数 echo $ref->getNumberOfRequiredParameters(); // 必需参数数量 $params = $ref->getParameters(); echo $params[0]->isCallable() ? 'callable' : 'not';一个小结:官方手册的文字介绍也值得读,但最快的信息增量来自签名里的可空类型、引用标记和返回类型。做兼容时,function_exists、extension_loaded与反射三件套可以避免大多数环境差异。看到反直觉的参数顺序时,在索引里做好笔记,比硬背下来可靠得多。
| 函数 | 引用参数 | 返回值与逻辑主体 | 容易记错的方向 |
|---|---|---|---|
| sort | &$array | 排序结果在参数里 | 有人当成返回新数组 |
| preg_match | &$matches | 匹配数通过返回值拿到,内容在参数里 | 匹配内容与返回值的对应关系 |
| str_replace | 无 | 返回替换后的新字符串 | 原字符串不变 |
| json_decode | 无 | 返回对象或数组,取决于参数 | 默认返回对象而非数组 |
3. 按分类熟悉内置函数:数组、字符串、文件与图像函数
3.1 数组函数组:map、filter、reduce 与带比较器的排序
数组函数占了 PHP 手册里相当大的篇幅,多数参考 PDF 也会按“数组处理—字符串处理—文件处理”来分章节。实际开发中最常用的是array_map、array_filter、array_reduce和以usort为代表的自定义排序四组。它们组合之后几乎能完成所有批量数据变换,比手写foreach更紧凑。
<?php $users = [ ['name' => 'Tom', 'age' => 23], ['name' => 'Ann', 'age' => 31], ['name' => 'Joe', 'age' => 19], ]; usort($users, fn($a, $b) => $a['age'] <=> $b['age']); $adultNames = array_map( fn($u) => $u['name'], array_filter($users, fn($u) => $u['age'] >= 20) ); $totalAge = array_reduce( array_filter($users, fn($u) => $u['age'] >= 20), fn($carry, $u) => $carry + $u['age'], 0 );usort的回调比较器用<=>飞船运算符返回 -1、0、1,这个模式在稍新的 PHP 代码中成为事实标准,常见于按时间、价格、优先级排序。注意array_filter默认会保留原数组的键名,所以如果想拿到连续的索引,得在结果外套一层array_values;想按需要保留键名时,这个默认行为反而是优点。array_reduce的第三个参数是初始值,请大家务必写成明确的0或[],避免类型混淆,比如把所有年龄相加时初始值传0,拼接字符串数组时初始值传[]更合理。
3.2 字符串函数组:多字节处理与正则的分隔符习惯
字符串函数里最容易出问题是把“字节数”当成“字符数”。strlen('中文')在 UTF-8 下返回 9,而mb_strlen('中文')返回 3。这个差异在多字节文本截取、长度校验和数据库字段限制场景里会产生连锁故障。读索引 PDF 时,建议一眼识别哪些函数名带mb_前缀,哪些不带,然后在自由文本处理中优先选择多字节版本。
<?php $text = ' 学好 PHP 函数,先从字符串开始。 '; $clean = trim($text); // 多字节长度,按字符数统计 echo mb_strlen($clean); // 按字节数统计,中文环境下结果通常会不同 echo strlen($clean); // 用正则按中文标点拆分,u 修饰符保证 Unicode 工作正常 $parts = preg_split('/[,。]/u', $clean); print_r($parts); // 字符串替换,注意替换源是数组时会按顺序匹配 $url = str_replace( ['https://', 'http://'], ['https://', 'https://'], 'http://example.com' );你也许在搜索引擎里见过“php序列化中文”之类的问题,本质也是serialize处理二进制字符串时,多字节内容会被urlencode后再存储,这与字符串函数里addslashes、stripslashes的边界问题类似。安全地处理用户输入时,不推荐用正则去过滤大段 HTML,而应该优先考虑htmlspecialchars、strip_tags这类针对性函数。在构造 SQL 或日志输出时,也别忘了addcslashes和escapeshellarg各自的适用面。函数名容易混,但每种转义都对应一个精确场景,这正是指南型 PDF 该有的价值。
3.3 文件、日期与图像函数组:IO 返回值的第一道检查
文件函数的重点不是读写本身,而是返回值判断。file_get_contents读取失败时返回false,但如果你直接把它传给json_decode,在 PHP 8 中会收到TypeError,因为json_decode的第一个参数要求必须是字符串。处理外部文件、接口返回、用户上传内容时,第一道防线就是判断是否拿到了预期的变量类型。
<?php // 读取本地 JSON 文件,并严格判断失败情况 $raw = file_get_contents('./data.json'); if ($raw === false) { throw new RuntimeException('配置读取失败'); } // JSON_THROW_ON_ERROR 让解析失败抛异常,而不是静默返回 null $data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR); // 日期计算使用 DateTimeImmutable,避免修改原对象 $start = new DateTimeImmutable('2025-01-01 00:00:00'); $end = $start->modify('+7 days'); echo $end->format('Y-m-d');还有一个常被忽略的是file_get_contents可以配合 stream context 设置超时,从远程 URL 拉取时特别有用。常见的做法是传入第二个参数false,第三个参数stream_context_create,这样请求超时不会卡死整个进程。至于图片处理的三个高频函数imagecreatetruecolor、imagecolorallocate、imagepng,它们在 GD 扩展里承担着“php图片生产”的场景:先在内存创建画布,再分配颜色,最后输出或保存文件。可以在一个带裁剪逻辑的函数里把它们串起来,但别忘了用function_exists('imagecreatetruecolor')做前置检查,因为很多精简镜像不会装 GD 扩展。
4. 掌握 PHP 函数调用的边界:动态调用、回调与错误处理
4.1 动态调用三种写法:可变函数、call_user_func、箭头函数
函数名本身也可以被当作变量存起来,这是很多灵活架构的基础。可变函数的语法是把字符串赋值给变量,再用变量加括号调用;call_user_func系列则用于需要动态决定调用方式的场景;箭头函数是 PHP 7.4 之后简化回调的常见写法。它们之间并不是替代关系,而是适用层级不同。
<?php // 方式一:可变函数,简单直观 $fn = 'strtoupper'; echo $fn('hello'); // 方式二:call_user_func_array,适合参数数量动态变化的场景 $result = call_user_func_array('array_merge', [['a'], ['b'], ['c']]); // 方式三:箭头函数,常用于单行回调 $ids = array_map(fn($user) => $user['id'], $users);可变函数的缺点是缺少静态分析和 IDE 提示,写框架或策略模式时适合,写业务代码时不推荐滥用。call_user_func_array常被用来构造“不知道参数个数”的动态调用,但性能略低于直接写函数调用。箭头的fn() =>语法会自动绑定外部变量,不需要再写use ($var),这种便利在array_filter、array_map里大量发光;当回调逻辑超过一行时,还是换成普通闭包更好,因为你给回调起个名字,日志和调试都会更清楚。“无法将 claude/cmake 识别为 cmdlet”那类热词对应的其实是终端工具调试问题,本质和 PHP 一样:先把函数或命令所在路径确认好,再谈调用方式。
4.2 函数错误处理:set_error_handler 与 Throwable 的分工
PHP 的错误处理分成两套体系:一套是传统的 Error,一套是异常 Exception。PHP 7 以后大部分错误变成了Throwable的子类,于是try/catch可以捕获更多运行期问题。内置函数很多来自旧世界,碰到危险操作时往往只会触发 Warning,比如file_get_contents去读一个不存在的文件。要统一处理这些提示,可以在入口处注册自己的错误处理函数,把 Warning 转换成抛出ErrorException。
<?php set_error_handler(function ($severity, $message, $file, $line) { if (!(error_reporting() & $severity)) { // 这条错误被当前错误报告级别忽略,交给 PHP 默认逻辑 return false; } throw new ErrorException($message, 0, $severity, $file, $line); }); try { $content = file_get_contents('/no/such/file.txt'); } catch (Throwable $e) { error_log('读取失败:' . $e->getMessage()); }这样处理后,老式函数抛出的 Warning 也能进入统一的异常流。但要注意,set_error_handler无法捕获编译错误、parse error和部分致命错误。这个机制适合为整站统一异常管理,不适合单独在一个函数内部反复重置。另一个常见的json_encode编码失败问题,则可以依赖JSON_THROW_ON_ERROR标志来抛异常,而不是接受默认的返回false,这能极大降低错误分支的空值传递。
4.3 重构时容易选错的三个函数边界
第一,str_replace配合数组替换时,替换顺序是长键优先,不同 PHP 版本中的行为细节略有差异,但结果可能不是你想的那样的“一一对应”。需要精确映射时,考虑strtr更可靠。第二,array_filter不传回调时,会丢掉所有值为假的数据,例如'0'这个字符串也会被移除,这在过滤用户提交数据时会造成意外,你的本意可能只是去掉空值。第三,json_decode的第二个参数决定返回对象还是数组,默认返回对象,习惯用数组访问的人要显式传true。
| 常见场景 | 推荐写法 | 易错写法 | 出错原因 |
|---|---|---|---|
| 文本按规则替换 | strtr($text, $map) | str_replace 数组混用 | 替换顺序与预期不一致 |
| 过滤空值但保留 0 | array_filter($arr, fn($v) => $v !== null && $v !== '') | array_filter($arr) | 假值会被统一过滤 |
| 解析 JSON 键名不规范 | json_decode($raw, true) | 忘记第二个参数 | 默认返回对象,访问方式不对 |
| 日期格式化 | DateTimeImmutable | date 函数改全局时区 | 全局时区影响使用者偏好 |
这条边界意识里最值得练的是“用自己的话解释返回值”。查看《PHP函数大全.pdf》里任意一个函数时,先不看示例,只根据签名说出这个函数会返回什么、失败时返回什么、是否修改原始数据。说不对,说明理解停留在名字记忆层面。等你能把array_map、preg_match、mb_substr都准确描述出来,很多重构中的隐藏 Bug 会在动笔之前就被排掉。
5. 生成你自己的 PHP 函数索引 PDF,比维护公开手册更贴近项目
5.1 用 token_get_all 统计项目里真正“再用”的函数
公开手册覆盖了几百个内置函数,但你项目里真正高频调用的可能只有几十个。与其背一份通用《PHP函数大全.pdf》,不如先从代码仓库里抓出真实使用频率,生成属于自己的精简索引。token_get_all能把 PHP 源码拆成 token 数组,其中T_STRING就是标识符,也就是潜在的函数名。
<?php $used = []; $tokens = token_get_all(file_get_contents(__FILE__)); foreach ($tokens as $t) { if (is_array($t) && $t[0] === T_STRING && function_exists($t[1])) { $used[$t[1]][] = $t[2]; // 函数名 => 行号列表 } } foreach ($used as $fn => $lines) { $ref = new ReflectionFunction($fn); echo $fn . ' 调用 ' . count($lines) . ' 次,签名:' . $ref->getNumberOfParameters() . " 参数\n"; }对仓库里所有 PHP 文件循环执行这段逻辑,把结果按调用次数排序,就能得到“我这个项目常用的 PHP 函数 TOP N”。继续用ReflectionFunction读取每个函数的参数数量、返回类型,甚至通过getExtensionName()知道它来自哪个扩展,比如来自mbstring还是gd。这些数据汇总后,正是个人版函数大全的主要骨架。
5.2 用生成脚本把函数清单输出成 Markdown 或 PDF 格式
拿到高频函数列表后,建议先输出成 Markdown 表格,列字段包括:函数名、扩展名、必填参数个数、常用签名、你项目里的调用次数、注意事项。这样一个项目维护一份,比网上转载的各种“PHP函数大全.pdf”都更有针对性。转成 PDF 的常见做法是把它交给 Pandoc 这类命令行工具生成,或者直接输出为 HTML 再通过浏览器的打印功能保存成 PDF,不需要依赖专门的桌面软件。
<?php // 生成 Markdown 摘要的雏形 $lines = []; foreach ($used as $fn => $linesOfCode) { $ref = new ReflectionFunction($fn); $lines[$fn] = sprintf( "| %s | %s | %d | %d 次 |\n", $fn, $ref->getExtensionName() ?: 'core', $ref->getNumberOfRequiredParameters(), count($linesOfCode) ); } file_put_contents('function-index.md', implode('', $lines));生成之后,最后一步做一次签名校验。方法是挑一个高频函数,比如mb_substr,用你们生产环境的php -r输出它的真实签名,再和索引里的签名对比。PHP 版本不同、扩展编译参数不同,函数的签名和可用与否都会出现差异。索引必须跟环境绑定,才不至于漏掉imagepng这类依赖 GD 扩展的函数。把生成脚本放进项目根目录,每季度重新跑一遍,这份自己的函数索引就会比静态 PDF 更符合实际系统需求。
本文还有配套的精品资源,点击获取