PHP 作為 Web 開發主流語言,內建大量強大且實用的核心功能。掌握這些功能能讓開發事半功倍,避免重複造輪子。本文精選 8 個高頻、高價值的 PHP 核心功能,從原理到實戰深度解析。
現代寫法 (PHP 5.6+):使用 ... 運算子(Splat operator)
<?php
function sum(...$numbers): float {
return array_sum($numbers);
}
echo sum(1, 2, 3, 4); // 10
echo sum(...[1, 2, 3]); // 6 (解包陣列)
function buildQuery(string $baseUrl, array $params = [], string ...$headers): string {
// $headers 為可變字串參數陣列
}
?>
舊版相容寫法:func_get_args()、func_num_args()、func_get_arg($i)
實戰場景:日誌封裝、SQL 建構器、多態方法、中介軟體管線
比 scandir() 更強大,支援通配符、多模式、遞迴(配合 GLOB_BRACE)
<?php
// 基礎用法
$phpFiles = glob('*.php'); // 當前目錄所有 .php
$imgFiles = glob('images/*.{jpg,png,gif}', GLOB_BRACE); // 多副檔名
// 遞迴掃描(需自行實現或用 RecursiveDirectoryIterator)
function globRecursive(string $pattern, int $flags = 0): array {
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_MARK) as $dir) {
$files = array_merge($files, globRecursive($dir . basename($pattern), $flags));
}
return $files;
}
$allPhp = globRecursive('**/*.php'); // 所有子目錄 .php 檔案
// 取得絕對路徑
$absolutePaths = array_map('realpath', glob('../uploads/*.pdf'));
?>
優勢:直接返回匹配檔案陣列,無需手動遍歷過濾,效能優於 scandir + fnmatch
<?php
function memoryProfile(callable $task, string $label = ''): void {
$start = memory_get_usage(true); // true = 系統分配的實際記憶體
$task();
$end = memory_get_usage(true);
$peak = memory_get_peak_usage(true);
echo "[$label] 當前: " . formatBytes($end - $start)
. " | 峰值: " . formatBytes($peak - $start) . "\n";
}
function formatBytes(int $bytes): string {
$units = ['B', 'KB', 'MB', 'GB'];
$i = 0;
while ($bytes >= 1024 && $i < count($units) - 1) {
$bytes /= 1024;
$i++;
}
return round($bytes, 2) . ' ' . $units[$i];
}
// 使用範例
memoryProfile(function() {
$data = [];
for ($i = 0; $i < 100000; $i++) {
$data[] = md5($i);
}
unset($data[50000]); // 釋放部分
}, '大陣列操作');
?>
應用:記憶體洩漏排查、大資料處理優化、CLI 長程序監控、PHP-FPM 進程記憶體限制調優
<?php
function cpuProfile(callable $task): array {
$before = getrusage();
$task();
$after = getrusage();
return [
'user_time_sec' => ($after['ru_utime.tv_sec'] - $before['ru_utime.tv_sec'])
+ ($after['ru_utime.tv_usec'] - $before['ru_utime.tv_usec']) / 1e6,
'system_time_sec' => ($after['ru_stime.tv_sec'] - $before['ru_stime.tv_sec'])
+ ($after['ru_stime.tv_usec'] - $before['ru_stime.tv_usec']) / 1e6,
'max_rss_kb' => $after['ru_maxrss'], // 最大駐留集大小 (KB)
'page_faults' => $after['ru_majflt'] - $before['ru_majflt'],
'context_switches' => ($after['ru_nvcsw'] - $before['ru_nvcsw'])
+ ($after['ru_nivcsw'] - $before['ru_nivcsw']),
];
}
// 區分 CPU 密集 vs I/O 密集
cpuProfile(function() {
for ($i = 0; $i < 1e7; $i++) {} // CPU 密集
});
// user_time 佔主導
cpuProfile(function() {
usleep(100000); // I/O 等待模擬
});
// system_time 相對較高
?>
指標解讀:ru_utime 用戶態 CPU 時間(執行你的代碼)、ru_stime 核心態 CPU 時間(系統調用)、ru_maxrss 記憶體峰值
<?php
// 檔案包含路徑解決(避免相對路徑問題)
require_once __DIR__ . '/config/database.php'; // PHP 5.3+
// 等價於 dirname(__FILE__)
// 除錯追蹤
function debugLog(string $msg): void {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1] ?? [];
echo "[{$trace['file']}:{$trace['line']}] $msg\n";
}
// 命名空間感知的工廠
class Factory {
public static function create(string $className): object {
$fullClass = __NAMESPACE__ . '\\Models\\' . $className;
return new $fullClass();
}
}
?>
| 常量 | 含義 | 典型用途 |
|---|---|---|
| __LINE__ | 當前行號 | 除錯日誌、錯誤定位 |
| __FILE__ | 完整檔案路徑 | 包含檔案、路徑解析 |
| __DIR__ | 檔案所在目錄 | 專案根目錄定位、資源載入 |
| __FUNCTION__ | 函數名 | 動態呼叫、除錯 |
| __CLASS__ | 類名(含命名空間) | 反射、序列化、日誌 |
| __METHOD__ | 類方法名 | 精確追蹤、效能分析 |
| __NAMESPACE__ | 當前命名空間 | 動態類載入、模組化架構 |
<?php
// 基礎:微秒時間戳 + 進程 ID,有序、較短
echo uniqid(); // 65a8f3c2d1e4b
echo uniqid('order_'); // order_65a8f3c2d1e4b (帶前綴,業務區分)
echo uniqid('', true); // 65a8f3c2d1e4b3.12345678 (more_entropy=true,更唯一)
echo uniqid('txn_', true); // txn_65a8f3c2d1e4b3.12345678
// 進階:結合隨機數用於高併發訂單號
function generateOrderId(): string {
return sprintf(
'%s%s%04d',
date('YmdHis'),
uniqid('', true), // 含微秒
random_int(1000, 9999)
);
}
// 2024011514302565a8f3c2d1e4b3.123456781234
?>
優勢:有序(利於資料庫索引)、無需協調、比 UUID 短、內建熵增強選項
注意:極高併發(萬級 QPS)可能重複,關鍵業務建議加分散式鎖或資料庫唯一約束雙重保障
<?php
$data = ['user' => 'admin', 'roles' => [1,2,3], 'meta' => (object)['ip' => '1.2.3.4']];
// PHP 原生序列化(保留類型、物件)
$serialized = serialize($data);
// a:3:{s:4:"user";s:5:"admin";s:5:"roles";a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}s:4:"meta";O:8:"stdClass":1:{s:2:"ip";s:7:"1.2.3.4";}}
$restored = unserialize($serialized); // 完整還原物件
// JSON 序列化(跨語言、可讀、Web 標準)
$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
// {"user":"admin","roles":[1,2,3],"meta":{"ip":"1.2.3.4"}}
$decoded = json_decode($json, true); // true = 關聯陣列
// 效能對比:JSON 通常快 2-3 倍,體積小 30-50%
// 安全性:unserialize 可能觸發 __wakeup/__destruct 攻擊,不可信資料嚴禁使用
?>
最佳實踐:
serialize(需信任來源)json_encodeigbinary、msgpack、protobuf(需擴充)<?php
$longText = str_repeat('PHP 字串壓縮測試內容...', 1000); // ~30KB
$compressed = gzcompress($longText, 6); // 壓縮等級 0-9 (6 平衡)
echo "原始: " . strlen($longText) . " bytes\n"; // ~30,000
echo "壓縮: " . strlen($compressed) . " bytes\n"; // ~2,000 (約 93% 壓縮率)
$decompressed = gzuncompress($compressed);
assert($decompressed === $longText);
// gzencode: 產生標準 gzip 檔案格式(含 Header/CRC),適合 HTTP 傳輸
$gzipped = gzencode($longText, 9, FORCE_GZIP);
header('Content-Encoding: gzip');
echo $gzipped; // 直接輸出給支援 gzip 的客戶端
?>
應用場景:
ob_gzhandler 或 Nginx gzip)| 需求 | 推薦功能 | 替代方案 |
|---|---|---|
| 不定參數函數 | ...$args (PHP 5.6+) | func_get_args() |
| 檔案掃描匹配 | glob() | RecursiveDirectoryIterator |
| 記憶體監控 | memory_get_usage(true) | Xdebug、Blackfire |
| CPU 分析 | getrusage() (Linux) | xhprof、Blackfire |
| 路徑/除錯資訊 | 魔術常量 __DIR__ 等 | debug_backtrace() |
| 唯一有序 ID | uniqid('', true) | UUID v7、Snowflake |
| 資料序列化 | json_encode (通用) / serialize (PHP 專用) | igbinary、msgpack |
| 字串壓縮 | gzcompress / gzencode | zstd、lz4 (需擴充) |
熟練運用這 8 大核心功能,能解決 80% 以上的日常開發痛點,是 PHP 進階開發者的必修課。