PHP 內建超過 1000 個函式,許多強大卻鮮為人知的「隱藏寶石」能解決特定棘手問題。本文精選 10 個高實用價值、低知名度的函式,附完整範例、適用場景與注意事項,擴展你的 PHP 工具箱。
<?php
// 回傳陣列 [1分鐘, 5分鐘, 15分鐘] 平均負載
$load = sys_getloadavg();
// 例: [0.45, 0.32, 0.28]
// 實戰:高負載時拒絕請求,保護系統穩定
if ($load[0] > 10.0) { // 1分鐘負載超過 CPU 核心數 10 倍
http_response_code(503);
header('Retry-After: 30');
die('系統過載,請稍後再試');
}
// 注意:Windows 環境回傳 false,需判斷
if ($load === false) {
// Windows 替代方案:wmic 或 performance counters
}
?>
<?php
// md5() 回傳 32 字元十六進位字串 (128 bits)
$hex = md5('secret'); // "5ebe2294ecd0e0f08eab7690d2a6ee69"
// pack('H*', ...) 將十六進位轉為 16 位元組二進位字串
$bin = pack('H*', $hex); // 長度 16 bytes,節省 50% 空間
// 資料庫儲存:BINARY(16) 欄位而非 CHAR(32)
// 反向解包
$hexRestored = unpack('H*', $bin)[1]; // 還原十六進位
// 其他常用格式
pack('N', 123456); // 32-bit 無號大端序 (網路位元組序)
pack('V', 123456); // 32-bit 無號小端序
pack('H*', 'ff00aa'); // 十六進位字串
pack('C*', 255,0,170); // 位元組陣列
?>
<?php
// 格里曆 (西曆)
echo cal_days_in_month(CAL_GREGORIAN, 2, 2024); // 29 (閏年)
echo cal_days_in_month(CAL_GREGORIAN, 2, 2023); // 28
// 猶太曆、法國共和曆等
echo cal_days_in_month(CAL_JEWISH, 7, 5784);
// 實戰:產生月曆
function renderCalendar(int $year, int $month): string {
$days = cal_days_in_month(CAL_GREGORIAN, $month, $year);
$firstDay = (int)date('w', strtotime("$year-$month-01")); // 0=週日
$html = "<table><tr><th>日</th><th>一</th>...<th>六</th></tr><tr>";
$html .= str_repeat("<td></td>", $firstDay);
for ($d = 1; $d <= $days; $d++) {
$html .= "<td>$d</td>";
if (($firstDay + $d) % 7 === 0) $html .= "</tr><tr>";
}
return $html . "</tr></table>";
}
?>
<?php
// 設定語言環境
putenv('LC_ALL=zh_TW.utf8');
setlocale(LC_ALL, 'zh_TW.utf8');
bindtextdomain('myapp', __DIR__ . '/locale');
textdomain('myapp');
// _() 回傳翻譯字串
$msg = _("Welcome to our website");
// _e() 直接輸出 (echo _())
_e("Welcome to our website");
// 進階:複數形式 ngettext()
printf(ngettext("%d file", "%d files", $count), $count);
// .po 檔案範例
/*
msgid "Welcome to our website"
msgstr "歡迎來到我們的網站"
msgid "%d file"
msgid_plural "%d files"
msgstr[0] "%d 個檔案"
msgstr[1] "%d 個檔案"
*/
?>
<?php
// 需 php_browscap.ini (從 https://browscap.org/ 下載放入 PHP 目錄)
// php.ini: browscap = /path/to/php_browscap.ini
$browser = get_browser(null, true); // true = 回傳陣列而非物件
/*
Array (
[browser_name_regex] => ^mozilla/5\.0 \(.*windows nt 10\.0.*\) applewebkit/.* \(khtml, like gecko\) chrome/.* safari/.*$
[browser_name_pattern] => Mozilla/5.0 (*Windows NT 10.0*) AppleWebKit/* (KHTML, like Gecko) Chrome/* Safari/*
[parent] => Chrome 120.0
[platform] => Win10
[browser] => Chrome
[version] => 120.0
[majorver] => 120
[minorver] => 0
[cssversion] => 3
[frames] => 1
[iframes] => 1
[tables] => 1
[cookies] => 1
[javascript] => 1
[vbscript] =>
[activexcontrols] =>
[isbanned] =>
[ismobiledevice] =>
[istablet] =>
[issyndicationreader] =>
[crawler] =>
...
)
*/
// 實戰:針對舊瀏覽器提供 Polyfill
if (isset($browser['javascript']) && !$browser['javascript']) {
echo '<script src="polyfill.min.js"></script>';
}
// 注意:無法偵測使用者「關閉 JS」的情況,只能判斷瀏覽器「能力」
?>
<?php
function a() { b(); }
function b() { c(); }
function c() {
echo "--- Backtrace ---\n";
debug_print_backtrace();
echo "\n-----------------\n";
}
a();
/*
輸出:
--- Backtrace ---
#0 c() called at [/path/file.php:2]
#1 b() called at [/path/file.php:1]
#2 a() called at [/path/file.php:5]
-----------------
*/
// 進階:取得陣列而非輸出
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); // 忽略參數節省記憶體
foreach ($trace as $frame) {
echo "{$frame['function']}() in {$frame['file']}:{$frame['line']}\n";
}
?>
<?php
// 相同發音 -> 相同 Metaphone 編碼
echo metaphone("phone"); // FN
echo metaphone("fone"); // FN
echo metaphone("phonetic"); // FNTK
// 實戰:模糊搜尋、姓名匹配
$names = ['Smith', 'Smyth', 'Smythe', 'Johnson', 'Jonson'];
$target = 'Smith';
$targetCode = metaphone($target);
foreach ($names as $name) {
if (metaphone($name) === $targetCode) {
echo "相似發音: $name\n"; // Smith, Smyth, Smythe
}
}
// 注意:僅適用英文,中文無效
?>
<?php
$items = ['img1.png', 'img10.png', 'img2.png', 'img20.png', 'img3.png'];
// 一般排序 (字典序)
sort($items);
// ['img1.png', 'img10.png', 'img2.png', 'img20.png', 'img3.png'] ❌
// 自然排序
natsort($items);
// ['img1.png', 'img2.png', 'img3.png', 'img10.png', 'img20.png'] ✅
// 關聯陣列保持鍵值
$files = [
'a' => 'file10.txt',
'b' => 'file2.txt',
'c' => 'file1.txt'
];
natsort($files);
// ['c'=>'file1.txt', 'b'=>'file2.txt', 'a'=>'file10.txt']
// 反向自然排序
$items = ['v1.2', 'v1.10', 'v1.1'];
natrsort($items); // ['v1.10', 'v1.2', 'v1.1']
?>
<?php
// 計算將字串 A 轉為 B 所需最少編輯操作 (插入/刪除/替換)
echo levenshtein('kitten', 'sitting'); // 3 (k→s, e→i, +g)
// 實戰:搜尋建議 "Did you mean...?"
$dict = ['php', 'javascript', 'python', 'java', 'go', 'rust'];
$input = 'phpp'; // 使用者輸入錯誤
$best = $dict[0];
$minDist = levenshtein($input, $best);
foreach ($dict as $word) {
$dist = levenshtein($input, $word);
if ($dist < $minDist) {
$minDist = $dist;
$best = $word;
}
}
echo "Did you mean '$best'? (distance: $minDist)"; // Did you mean 'php'? (distance: 1)
// 自訂成本 (插入、替換、刪除權重不同)
echo levenshtein('a', 'b', 1, 2, 1); // 替換成本 2
?>
<?php
// 尋找所有 .php 檔案
foreach (glob("*.php") as $file) {
echo "$file\n";
}
// 遞迴尋找 (需 PHP 5.5+ GLOB_BRACE)
$phpFiles = glob("**/*.php", GLOB_BRACE); // 需支援 ** 模式或用 RecursiveDirectoryIterator
// 更強大的替代:GlobIterator
$it = new GlobIterator("*.php");
foreach ($it as $file) {
echo $file->getFilename() . " (" . $file->getSize() . " bytes)\n";
}
// 常用模式
glob("*.{php,html,css,js}", GLOB_BRACE); // 多副檔名
glob("../data/*.csv"); // 相對路徑
glob("/var/log/*.log", GLOB_NOSORT); // 不排序 (大量檔案較快)
glob("*", GLOB_ONLYDIR); // 僅目錄
glob("*", GLOB_MARK); // 目錄名加斜線
// 注意:Windows 路徑分隔符為 \,glob() 接受 / 並自動轉換
?>
| 函式 | 核心用途 | 關鍵限制 | 替代/補充 |
|---|---|---|---|
| sys_getloadavg | 系統負載監控 | 僅 Linux/Unix | Windows: wmic / performance counters |
| pack/unpack | 二進位序列化 | 格式字串複雜 | MessagePack, Protocol Buffers |
| cal_days_in_month | 月份天數 | 需 calendar 擴充 (通常內建) | date('t') 簡易版 |
| _()/_e() | Gettext 翻譯 | 需 .po/.mo 檔案、locale 設定 | Symfony Translation, Laravel __() |
| get_browser | 瀏覽器能力 | 需 browscap.ini、無法偵測使用者設定 | User-Agent 解析庫 (UAParser) |
| debug_print_backtrace | 除錯堆疊 | 僅輸出,不回傳 | debug_backtrace() 回傳陣列 |
| metaphone | 英文發音編碼 | 僅英文 | soundex(), Double Metaphone |
| natsort | 自然排序 | 修改原陣列、不支援多維 | usort + strnatcmp |
| levenshtein | 編輯距離 | 長字串 O(n*m) 慢、>255 字元回傳 -1 | similar_text(), 外部演算法庫 |
| glob | 檔案模式匹配 | 不支援遞迴 ** (需迭代器) | RecursiveDirectoryIterator, Finder |
false,必須判斷,否則 $load[0] 會報錯。true 參數。-1,長字串需分段或用其他演算法。basename() 取純檔名。