PHP 不允許同名函數多態定義。但利用 func_num_args()、func_get_arg()、func_get_args() 三大函數,可實現**參數數量/類型自適應**的偽重載模式。
| 函數 | 返回值 |
|---|---|
func_num_args() | 實際傳入參數個數 |
func_get_arg(int $pos) | 指定位置參數值(0 基) |
func_get_args() | 所有參數組成的陣列 |
function test() {
$argc = func_num_args();
$argv = func_get_args(); // 更簡潔
switch ($argc) {
case 0: echo "無參數\n"; break;
case 1: testOne($argv[0]); break;
case 2: testTwo($argv[0], $argv[1]); break;
case 3: testThree($argv[0], $argv[1], $argv[2]); break;
default: echo "參數過多\n";
}
}
function testOne($a) { echo "1 參數: $a\n"; }
function testTwo($a, $b) { echo "2 參數: $a, $b\n"; }
function testThree($a, $b, $c) { echo "3 參數: $a, $b, $c\n"; }
test(); // 無參數
test(1); // 1 參數: 1
test(1, 2); // 2 參數: 1, 2
test(1, 2, 3); // 3 參數: 1, 2, 3
class Config {
private $host = 'localhost';
private $port = 3306;
private $user = 'root';
private $pass = '';
public function __construct() {
$args = func_get_args();
switch (count($args)) {
case 1: $this->initFromDsn($args[0]); break;
case 2: $this->host = $args[0]; $this->port = $args[1]; break;
case 4: [$this->host, $this->port, $this->user, $this->pass] = $args; break;
default: throw new InvalidArgumentException('Invalid args');
}
}
private function initFromDsn(string $dsn) { /* parse */ }
}
new Config('mysql:host=localhost;dbname=test');
new Config('localhost', 3306);
new Config('localhost', 3306, 'user', 'pass');
| 特性 | 版本 | 語法示例 |
|---|---|---|
| 可變參數 | 5.6 | function foo(...$args) 替代 func_get_args() |
| 參數解包 | 5.6 | call_user_func_array([$obj, 'method'], $args) → $obj->method(...$args) |
| 標量類型聲明 | 7.0 | function foo(int $a, string $b = ''): bool |
| 聯合類型 | 8.0 | function foo(int|float $num) |
| 命名參數 | 8.0 | foo(a: 1, c: 3) 跳過可選參數 |
...$args 覆蓋 90% 場景func_get_args() 會複製參數陣列,頻繁調用有記憶體/CPU 開銷。熱路徑建議:
function foo($a = null, $b = null, $c = null) 手動判斷偽重載是 PHP 早期缺乏現代語言特性時的權宜之計,隨版本演進已逐步退出歷史舞台,了解其原理有助於閱讀遺留代碼與理解語言演進邏輯。