首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 那些強大卻被忽略的函數:call_user_func、create_function、register_shutdown_function 等實戰詳解

     編輯:PHP 綜合知識

前言

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 回調

重點函數深度解析

1. call_user_func / call_user_func_array - 動態調度核心

// 基礎用法
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

2. func_get_args 族 - 可變參數函數的基石

// 實作類似 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

3. register_shutdown_function - 關機前的最後一舞

無論 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();

4. Tick 機制 - 程式碼執行監控(慎用)

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 會嚴重拖慢執行速度(數十倍),僅限開發環境除錯/分析,嚴禁生產環境開啟。

5. create_function - 歷史遺物(PHP 7.2 棄用,8.0 移除)

// 舊寫法(請勿在新專案使用)
$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 是「最後防線」,善用於錯誤上報與清理
  • Tick:只作為 開發期 分析工具,如配合 Xdebug/Blackfire 更佳
  • create_function:完全避免使用,改用匿名函數/箭頭函數
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved