PHP 擁有上千個內建函數,許多強大功能藏在冷門函數中。本文精選 11 個高實用性、低知名度的函數,附完整範例說明應用場景。
| 分類 | 函數 | 核心用途 |
|---|---|---|
| 動態呼叫 | call_user_func | 呼叫函數/方法,支援參數列表 |
call_user_func_array | 以陣列傳參呼叫,適合參數數量不固定 | |
create_function | 建立匿名函數(PHP 7.2+ 棄用,改用匿名函數語法) | |
| 參數檢查 | func_get_arg | 取得指定索引參數值 |
func_get_args | 取得所有參數陣列 | |
func_num_args | 取得參數個數 | |
| 函數管理 | function_exists | 檢查函數是否存在(含內建與自訂) |
get_defined_functions | 列出所有已定義函數 | |
register_shutdown_function | 註冊腳本結束前執行的函數 | |
| Tick 機制 | register_tick_function | 註冊每 N 條低級指令執行的回調 |
unregister_tick_function | 移除 tick 回調 |
// 基礎用法
function greet($name, $suffix = '!') {
echo "Hello, $name$suffix\n";
}
call_user_func('greet', 'World'); // Hello, World!
call_user_func('greet', 'PHP', '...'); // Hello, PHP...
// 陣列傳參版(參數動態決定時極佳)
$args = ['Laravel', ' 🚀'];
call_user_func_array('greet', $args); // Hello, Laravel 🚀
// 類方法呼叫(靜態/實例皆可)
class Service {
public function process($data) { echo "Processing: $data\n"; }
}
call_user_func([Service::class, 'process'], 'Order#123'); // 靜態
call_user_func([new Service(), 'process'], 'Order#456'); // 實例
// 支援參考傳遞
function increment(&$n) { $n++; }
$val = 10;
call_user_func('increment', $val); // $val 變 11
call_user_func_array('increment', [&$val]); // $val 變 12
// 實作類似 JS console.log 的多參數輸出
function log(...$args) { // PHP 5.6+ 可直接用 ...$args
// 舊版寫法:
// $args = func_get_args();
$prefix = '[LOG ' . date('H:i:s') . '] ';
echo $prefix . implode(' ', array_map(function($v) {
return is_scalar($v) ? (string)$v : json_encode($v, JSON_UNESCAPED_UNICODE);
}, $args)) . "\n";
}
log('User login', ['id' => 123, 'ip' => '1.2.3.4'], true);
// [LOG 14:30:01] User login {"id":123,"ip":"1.2.3.4"} 1
無論 exit()、致命錯誤、或正常結束,都會執行(除非 posix_kill 或 SIGKILL)。
// 應用:效能監控、錯誤收集、資源清理
register_shutdown_function(function() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR])) {
// 致命錯誤通知
error_log("FATAL: {$error['message']} in {$error['file']}:{$error['line']}");
// 可發送 Slack/Email/寫入資料庫
}
// 輸出執行時間
error_log("Request time: " . (microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) . "s");
});
echo "Script running...\n";
// 模擬致命錯誤:取消註解下行測試
// non_existent_function();
declare(ticks=1); // 每 1 條低級指令觸發
$counter = 0;
register_tick_function(function() use (&$counter) {
$counter++;
if ($counter % 10000 === 0) {
echo "Executed $counter ticks\n";
}
});
// 這裡的迴圈會觸發大量 tick
for ($i = 0; $i < 100000; $i++) {
// do something
}
unregister_tick_function('tick_handler');
⚠️ 警告:Tick 會嚴重拖慢執行速度(數十倍),僅限開發環境除錯/分析,嚴禁生產環境開啟。
// 舊寫法(請勿在新專案使用)
$adder = create_function('$a,$b', 'return $a + $b;');
echo $adder(2, 3); // 5
// 現代寫法(匿名函數 + 閉包)
$adder = fn($a, $b) => $a + $b; // PHP 7.4+ 箭頭函數
// 或
$adder = function($a, $b) { return $a + $b; };
class EventDispatcher {
private $listeners = [];
public function on(string $event, callable $handler): void {
$this->listeners[$event][] = $handler;
}
public function emit(string $event, ...$args): void {
foreach ($this->listeners[$event] ?? [] as $handler) {
call_user_func_array($handler, $args);
}
}
}
// 使用
$dispatcher = new EventDispatcher();
$dispatcher->on('order.created', function($orderId) {
echo "發送確認信: $orderId\n";
});
$dispatcher->on('order.created', function($orderId) {
echo "更新庫存: $orderId\n";
});
$dispatcher->emit('order.created', 'ORD-20240101-001');
call_user_func_array 搭配 ... 運算子(PHP 5.6+)register_shutdown_function 是「最後防線」,善用於錯誤上報與清理