PHP 的函數系統極其靈活,支援魔術方法、匿名函數、閉包、嵌套函數、條件函數、動態調用與參數檢測等高級特性。掌握這些機制,能編寫出更優雅、可擴展的代碼。
魔術方法是 PHP 內置的語言特性,當特定條件觸發時自動調用。常見魔術方法:
__construct / __destruct:構造/析構__call / __callStatic:調用不可訪問的方法__get / __set / __isset / __unset:屬性重載__sleep / __wakeup:序列化控制__toString:對象轉字符串__clone:克隆行為__autoload(已棄用,改用 spl_autoload_register):自動加載類文件function __autoload($class_name) {
require_once $class_name . '.class.php';
}
// 放入 common.php,new Class_A 時自動加載 Class_A.class.php
__FILE__、__CLASS__:當前文件路徑、類名get_included_files():已包含文件列表dirname():獲取目錄部分$func = create_function('$a,$b', 'return ($a==$b)?0:(($a<$b)?-1:1);');
$func = function($a, $b) {
return ($a == $b) ? 0 : (($a < $b) ? -1 : 1);
};
usort($arr, $func); // 作為回調
$func(3, 4); // 直接調用
function foo($arg1) {
$var = 3;
$inner = function($innerArg) use ($arg1, $var) {
return $innerArg + $arg1 / $var;
};
echo $inner(5); // 輸出 5 + arg1/3
}
閉包在 PHP 中被實現為內置 Closure 類,但不能動態添加屬性($inner->a = 5 非法),不如 JavaScript 靈活。
function outer() {
$out_var = 1;
function inner() {
var_dump($out_var); // NULL,無法訪問外部變量
echo "call inner\n";
}
inner();
}
outer();
inner(); // 全局可見,但必須先調用 outer() 定義
關鍵點:內部函數無法訪問外部函數的局部變量(非閉包),且內部函數定義在全局命名空間,必須先執行外部函數才能調用內部函數。
$debug = false;
if ($debug === true) {
function foo() { echo "foo"; }
}
foo(); // 若 $debug=false,報錯:函數未定義
類似條件編譯,函數定義在 if 塊中,僅在條件滿足時被「編譯」進函數表。
$func = 'foo';
$func(); // 調用 foo()
安全建議:使用白名單或統一前綴(act_$funcName),調用前用 function_exists() 檢查。
call_user_func('foo', $arg1, $arg2);
call_user_func_array('foo', [$arg1, $arg2]);
// 調用類方法
call_user_func([$obj, 'method']);
call_user_func(['MyClass', 'staticMethod']);
call_user_func([$obj, 'method'], ...$args); // PHP 5.6+
get_defined_functions(); // 返回 ['internal' => [...], 'user' => [...]]
func_get_arg($n); // 獲取第 n 個參數
func_num_args(); // 參數總數
func_get_args(); // 所有參數數組
function call_it($func) {
$args = func_get_args();
array_shift($args);
call_user_func_array($func, $args);
}
call_it('add', 1, 2); // 輸出 3
call_it('sqr', 2); // 輸出 4
PHP 函數機制強大而靈活,合理運用魔術方法簡化對象操作、用閉包替代全局狀態、用動態調用實現插件架構,能顯著提升代碼質量。但需注意:嵌套/條件函數易導致維護困難,生產環境建議優先使用類與閉包。