Skip to content

内置函数

概述

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日期处理
JSONjson_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";
// &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;

数组函数

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"; // 255

JSON 处理函数

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_contains8.0字符串是否包含子串
str_starts_with8.0字符串是否以指定前缀开始
str_ends_with8.0字符串是否以指定后缀结束
array_key_first8.0获取数组第一个键
array_key_last8.0获取数组最后一个键
get_debug_type8.0获取变量类型的可读名称
array_is_list8.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] => [...] )

注意事项

常见陷阱

  1. 函数名大小写不敏感:内置函数名不区分大小写,但推荐使用小写
php
<?php

declare(strict_types=1);

// 都可以工作,但推荐小写
echo strlen('hello') . "\n";  // 推荐
echo StrLen('hello') . "\n";  // 可以但不推荐
echo STRLEN('hello') . "\n";  // 可以但不推荐
  1. 扩展依赖:某些常用函数需要安装扩展
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";
}
  1. 函数参数顺序不一致

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"; // snakeCaseString

3. 使用 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!');

参考链接