内置函数
概述
PHP 提供了数千个内置函数(Built-in Functions),覆盖字符串处理、数组操作、数学计算、文件系统、网络通信等几乎所有常见场景。内置函数随 PHP 核心一起安装,无需额外配置即可使用。合理利用内置函数可以大幅减少代码量并提高性能。
PHP 版本说明
- PHP 内置函数随各版本持续增加和改进
- 某些函数依赖特定扩展(如
mb_*系列依赖mbstring) - 使用
extension_loaded()检查扩展是否可用 - PHP 8.1+ 新增和改进了多个字符串和数组函数
基础概念
内置函数分类
PHP 内置函数按功能可分为以下主要类别:
| 类别 | 示例函数 | 说明 |
|---|---|---|
| 字符串处理 | strlen, substr, str_replace, explode | 字符串操作 |
| 数组操作 | array_map, array_filter, sort, array_merge | 数组处理 |
| 数学函数 | abs, ceil, floor, max, min | 数学计算 |
| 文件系统 | file_get_contents, file_put_contents, glob | 文件读写 |
| 日期时间 | date, time, strtotime, DateTime | 日期处理 |
| JSON | json_encode, json_decode | 数据序列化 |
| 正则表达式 | preg_match, preg_replace, preg_split | 模式匹配 |
| 网络函数 | curl_init, file_get_contents (URL) | 网络请求 |
| 加密安全 | password_hash, hash, openssl_* | 安全处理 |
内置函数 vs 用户自定义函数
| 特性 | 内置函数 | 用户自定义函数 |
|---|---|---|
| 定义位置 | PHP 核心或扩展中 | 用户代码中 |
| 执行速度 | 更快(C 语言实现) | 较慢(PHP 编译执行) |
| 覆盖/重定义 | 不允许 | 不允许同名 |
| 类型安全 | 因函数而异 | 由用户控制 |
| 文档 | php.net 完整文档 | 需自行编写 |
语法与代码
字符串函数
php
<?php
declare(strict_types=1);
// 常用字符串函数
$string = 'Hello, World!';
// 查找和截取
echo strlen($string) . "\n"; // 13
echo substr($string, 7) . "\n"; // World!
echo strpos($string, 'World') . "\n"; // 7
echo str_contains($string, 'World') ? 'yes' : 'no'; // yes (PHP 8.0+)
// 替换和格式化
echo str_replace('World', 'PHP', $string) . "\n"; // Hello, PHP!
echo str_pad('42', 5, '0', STR_PAD_LEFT) . "\n"; // 00042
echo trim(' hello ') . "\n"; // hello
// 拆分和合并
$parts = explode(',', 'apple,banana,cherry');
echo implode(' - ', $parts) . "\n"; // apple - banana - cherry
// 大小写和编码
echo strtoupper('hello') . "\n"; // HELLO
echo ucfirst('hello world') . "\n"; // Hello world
echo mb_strlen('你好世界') . "\n"; // 4(需要 mbstring 扩展)
// 安全处理
$html = '<script>alert("XSS")</script>';
echo htmlspecialchars($html, ENT_QUOTES, 'UTF-8') . "\n";
// <script>alert("XSS")</script>数组函数
php
<?php
declare(strict_types=1);
// 数组基本操作
$fruits = ['apple', 'banana', 'cherry', 'date'];
// 过滤和映射
$longFruits = array_filter($fruits, fn(string $f) => strlen($f) > 5);
print_r($longFruits); // Array ( [2] => cherry [3] => date )
$upperFruits = array_map(fn(string $f) => strtoupper($f), $fruits);
print_r($upperFruits); // Array ( [0] => APPLE [1] => BANANA ... )
// 排序
$numbers = [3, 1, 4, 1, 5, 9, 2, 6];
sort($numbers);
print_r($numbers); // Array ( [0] => 1 [1] => 1 [2] => 2 ... )
$assoc = ['b' => 2, 'a' => 1, 'c' => 3];
asort($assoc); // 按值排序
print_r($assoc); // Array ( [a] => 1 [b] => 2 [c] => 3 )
// 归约
$sum = array_reduce($numbers, fn(int $carry, int $item) => $carry + $item, 0);
echo "Sum: {$sum}\n"; // Sum: 31
// 合并和差集
$defaults = ['debug' => false, 'cache' => true, 'log' => true];
$userConfig = ['debug' => true, 'theme' => 'dark'];
$merged = array_merge($defaults, $userConfig);
print_r($merged);
// Array ( [debug] => true [cache] => true [log] => true [theme] => dark )
// 搜索和验证
echo in_array('banana', $fruits) ? 'found' : 'not found'; // found
$key = array_search('cherry', $fruits);
echo "Key: {$key}\n"; // Key: 2数学函数
php
<?php
declare(strict_types=1);
// 基本数学函数
echo abs(-42) . "\n"; // 42
echo ceil(3.14) . "\n"; // 4
echo floor(3.14) . "\n"; // 3
echo round(3.14159, 2) . "\n"; // 3.14
// 最大最小值
echo max(1, 5, 3, 9, 2) . "\n"; // 9
echo min(1, 5, 3, 9, 2) . "\n"; // 1
echo max([10, 20, 30]) . "\n"; // 30
// 格式化
echo number_format(1234567.891, 2, '.', ',') . "\n"; // 1,234,567.89
echo number_format(0.12345, 3, '.', '') . "\n"; // 0.123
// 随机数(PHP 8.2+ 推荐)
echo random_int(1, 100) . "\n"; // 1-100 之间的随机整数(加密安全)
echo random_bytes(16) . "\n"; // 16 字节随机二进制数据
// 进制转换
echo bindec('1010') . "\n"; // 10
echo decbin(10) . "\n"; // 1010
echo base_convert('ff', 16, 10) . "\n"; // 255JSON 处理函数
php
<?php
declare(strict_types=1);
// JSON 编码
$data = [
'name' => 'Alice',
'age' => 30,
'active' => true,
'skills' => ['PHP', 'JavaScript'],
];
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
echo $json . "\n";
// {
// "name": "Alice",
// "age": 30,
// "active": true,
// "skills": ["PHP", "JavaScript"]
// }
// JSON 解码
$decoded = json_decode($json, true);
echo $decoded['name'] . "\n"; // Alice
// 错误处理
$invalidJson = '{invalid}';
$result = json_decode($invalidJson);
if (json_last_error() !== JSON_ERROR_NONE) {
echo "JSON Error: " . json_last_error_msg() . "\n";
// JSON Error: Syntax error
}
// 深度控制
$deepData = array_fill(0, 10, array_fill(0, 10, 'x'));
echo json_encode($deepData, JSON_PRETTY_PRINT | JSON_DEPTH_LIMIT_ERROR) ? 'ok' : 'error';详细说明
检查扩展是否加载
某些内置函数需要特定扩展支持。使用 extension_loaded() 或 function_exists() 进行检查。
php
<?php
declare(strict_types=1);
// 检查扩展是否加载
function hasExtension(string $name): bool
{
return extension_loaded($name);
}
echo "mbstring: " . (hasExtension('mbstring') ? 'loaded' : 'not loaded') . "\n";
echo "curl: " . (hasExtension('curl') ? 'loaded' : 'not loaded') . "\n";
echo "json: " . (hasExtension('json') ? 'loaded' : 'not loaded') . "\n";
// 检查函数是否存在
if (function_exists('mb_strlen')) {
echo "mb_strlen available\n";
echo mb_strlen('中文') . "\n"; // 2
} else {
echo "mb_strlen not available, fallback to strlen\n";
}
// 安全调用扩展函数的封装
function safeMbStrlen(string $str): int
{
if (function_exists('mb_strlen')) {
return mb_strlen($str, 'UTF-8');
}
return strlen($str);
}
echo safeMbStrlen('Hello') . "\n"; // 5
echo safeMbStrlen('你好') . "\n"; // 2自定义函数与内置函数同名处理
PHP 不允许定义与内置函数同名的函数(除非在命名空间中)。如果在项目中需要覆盖内置函数的行为,推荐使用命名空间。
php
<?php
declare(strict_types=1);
// 全局命名空间不能覆盖内置函数
// function strlen($str) { ... } // Fatal error: Cannot redeclare strlen()
// 在命名空间中可以定义同名函数
namespace App\Utils;
function strlen(string $value): int
{
// 自定义实现
return \strlen($value); // 调用内置函数使用反斜杠前缀
}
function arrayMerge(array ...$arrays): array
{
// 自定义逻辑,调用内置函数
return \array_merge(...$arrays);
}
// 使用示例
namespace App;
use function App\Utils\strlen;
echo strlen('hello'); // 调用自定义函数
echo \strlen('hello'); // 调用内置函数命名空间注意
在命名空间中调用全局内置函数时,需要使用反斜杠前缀 \strlen(),否则 PHP 会在当前命名空间中查找该函数。
PHP 8.x 新增内置函数
PHP 8.x 版本新增了许多实用内置函数:
| 函数 | 版本 | 说明 |
|---|---|---|
str_contains | 8.0 | 字符串是否包含子串 |
str_starts_with | 8.0 | 字符串是否以指定前缀开始 |
str_ends_with | 8.0 | 字符串是否以指定后缀结束 |
array_key_first | 8.0 | 获取数组第一个键 |
array_key_last | 8.0 | 获取数组最后一个键 |
get_debug_type | 8.0 | 获取变量类型的可读名称 |
array_is_list | 8.1 | 检查数组是否为从 0 开始的连续索引列表 |
php
<?php
declare(strict_types=1);
// PHP 8.0+ 新增字符串函数
$filename = 'report-2024.pdf';
echo str_starts_with($filename, 'report-') ? 'yes' : 'no'; // yes
echo str_ends_with($filename, '.pdf') ? 'yes' : 'no'; // yes
echo str_contains($filename, '2024') ? 'yes' : 'no'; // yes
// PHP 8.0+ 新增数组函数
$config = ['host' => 'localhost', 'port' => 3306, 'db' => 'test'];
echo array_key_first($config) . "\n"; // host
echo array_key_last($config) . "\n"; // db
// PHP 8.1+ array_is_list
$isList1 = array_is_list([1, 2, 3]); // true
$isList2 = array_is_list([0 => 'a', 1 => 'b']); // true
$isList3 = array_is_list([1 => 'a', 2 => 'b']); // false(不从 0 开始)
$isList4 = array_is_list(['key' => 'value']); // false(非数字键)
// PHP 8.0+ get_debug_type
echo get_debug_type(42) . "\n"; // int
echo get_debug_type('hello') . "\n"; // string
echo get_debug_type([1, 2]) . "\n"; // array
echo get_debug_type(null) . "\n"; // null
echo get_debug_type(new stdClass()) . "\n"; // stdClass实战示例
数据清洗工具集
php
<?php
declare(strict_types=1);
function sanitizeInput(string $input): string
{
$input = trim($input);
$input = stripslashes($input);
$input = htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');
return $input;
}
function validateUrl(string $url): bool
{
return filter_var($url, FILTER_VALIDATE_URL) !== false;
}
function validateIpAddress(string $ip): bool
{
return filter_var($ip, FILTER_VALIDATE_IP) !== false;
}
function generateSlug(string $text): string
{
$text = transliterator_transliterate('Any-Latin; Latin-ASCII; Lower()', $text);
$text = preg_replace('/[^a-z0-9]+/', '-', $text);
return trim($text, '-');
}
// 使用示例
echo sanitizeInput(' <script>alert("xss")</script> ') . "\n";
echo validateUrl('https://www.example.com') ? 'valid' : 'invalid'; // valid
echo validateIpAddress('192.168.1.1') ? 'valid' : 'invalid'; // valid
echo generateSlug('Hello World! PHP 教程') . "\n"; // hello-world-php-jiao-cheng数组数据转换工具
php
<?php
declare(strict_types=1);
// 数组列提取(类似 Laravel 的 Arr::pluck)
function arrayPluck(array $items, string $key, ?string $indexKey = null): array
{
$result = [];
foreach ($items as $item) {
if (!is_array($item) && !$item instanceof ArrayAccess) {
continue;
}
$value = $item[$key] ?? null;
if ($indexKey !== null) {
$result[$item[$indexKey]] = $value;
} else {
$result[] = $value;
}
}
return $result;
}
// 数组按指定键分组
function arrayGroupBy(array $items, string $key): array
{
$groups = [];
foreach ($items as $item) {
$groupKey = $item[$key] ?? 'ungrouped';
if (!isset($groups[$groupKey])) {
$groups[$groupKey] = [];
}
$groups[$groupKey][] = $item;
}
return $groups;
}
// 使用示例
$users = [
['id' => 1, 'name' => 'Alice', 'dept' => 'Engineering'],
['id' => 2, 'name' => 'Bob', 'dept' => 'Marketing'],
['id' => 3, 'name' => 'Charlie', 'dept' => 'Engineering'],
['id' => 4, 'name' => 'Diana', 'dept' => 'Marketing'],
];
$names = arrayPluck($users, 'name', 'id');
print_r($names);
// Array ( [1] => Alice [2] => Bob [3] => Charlie [4] => Diana )
$byDept = arrayGroupBy($users, 'dept');
print_r($byDept);
// Array ( [Engineering] => [...], [Marketing] => [...] )注意事项
常见陷阱
- 函数名大小写不敏感:内置函数名不区分大小写,但推荐使用小写
php
<?php
declare(strict_types=1);
// 都可以工作,但推荐小写
echo strlen('hello') . "\n"; // 推荐
echo StrLen('hello') . "\n"; // 可以但不推荐
echo STRLEN('hello') . "\n"; // 可以但不推荐- 扩展依赖:某些常用函数需要安装扩展
php
<?php
declare(strict_types=1);
// JSON 扩展(PHP 默认启用)
echo json_encode(['key' => 'value']) . "\n";
// cURL 扩展(可能需要手动安装)
if (extension_loaded('curl')) {
$ch = curl_init('https://www.example.com');
// ...
} else {
echo "cURL extension is not available\n";
}
// GD 扩展(图像处理)
if (extension_loaded('gd')) {
$image = imagecreatetruecolor(100, 100);
// ...
} else {
echo "GD extension is not available\n";
}- 函数参数顺序不一致
PHP 内置函数的参数顺序有时不一致,需要查阅文档确认。
php
<?php
declare(strict_types=1);
// 注意参数顺序
in_array($needle, $haystack); // 先 needle 后 haystack
array_search($needle, $haystack); // 先 needle 后 haystack
array_map($callback, $array); // 先 callback 后 array
array_filter($array, $callback); // 先 array 后 callback(与 array_map 相反!)
strpos($haystack, $needle); // 先 haystack 后 needle(与 in_array 相反!)
substr($string, $start, $length); // string 在前
str_replace($search, $replace, $subject); // search, replace, subject参数顺序
内置函数的参数顺序没有统一的规范,建议在使用前查阅官方文档。IDE 的参数提示功能也很有帮助。
最佳实践
1. 优先使用内置函数
php
<?php
declare(strict_types=1);
// 推荐:使用内置函数
$isUpper = strtoupper($str) === $str;
// 不推荐:自己实现
function isUpperCase(string $str): bool
{
for ($i = 0; $i < strlen($str); $i++) {
if (ctype_lower($str[$i])) {
return false;
}
}
return true;
}2. 封装常用操作
虽然应优先使用内置函数,但对于频繁使用的组合操作,可以封装为自定义函数以提高代码可读性。
php
<?php
declare(strict_types=1);
function truncate(string $str, int $length = 100, string $suffix = '...'): string
{
if (mb_strlen($str, 'UTF-8') <= $length) {
return $str;
}
return mb_substr($str, 0, $length, 'UTF-8') . $suffix;
}
function toSnakeCase(string $input): string
{
return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $input));
}
function toCamelCase(string $input): string
{
return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $input))));
}
echo truncate('A very long string that needs to be truncated', 20) . "\n";
echo toSnakeCase('camelCaseString') . "\n"; // camel_case_string
echo toCamelCase('snake_case_string') . "\n"; // snakeCaseString3. 使用 PHP 8+ 新函数替代旧写法
php
<?php
declare(strict_types=1);
// PHP 8.0+
$haystack = 'Hello, World!';
// 旧写法
$old = strpos($haystack, 'World') !== false;
// 新写法(PHP 8.0+)
$new = str_contains($haystack, 'World');
// 旧写法
$oldStart = strpos($haystack, 'Hello') === 0;
$oldEnd = substr($haystack, -6) === 'orld!';
// 新写法
$newStart = str_starts_with($haystack, 'Hello');
$newEnd = str_ends_with($haystack, 'World!');