PHP 不支援編譯時重載,但通過運行時參數檢測可實現「偽重載」。本文系統總結四種實現方案,從簡單到複雜,並對比現代 PHP 原生特性的優勢。
<?php
function connect(string $host, int $port = 3306, string $user = 'root', string $pass = '', string $db = '') {
// 所有參數可選,調用極其靈活
// connect('localhost')
// connect('localhost', 3307)
// connect('localhost', 3306, 'admin', 'secret', 'mydb')
}
✅ 優點:語法原生、IDE 完美提示、類型安全、無運行時開銷
❌ 缺點:參數順序固定、無法跳過中間參數
<?php
function rewrite() {
$args = func_get_args();
$count = func_num_args();
match ($count) {
1 => func1($args[0]),
2 => func2($args[0], $args[1]),
default => throw new BadFunctionCallException("不支援 $count 參數"),
};
}
function func1($arg) { echo "1參數: $arg"; }
function func2($arg1, $arg2) { echo "2參數: $arg1, $arg2"; }
rewrite('PHP'); // 1參數: PHP
rewrite('PHP', 'China'); // 2參數: PHP, China
<?php
function createUser(array $options = []): User {
$defaults = [
'name' => '',
'email' => '',
'role' => 'user',
'active' => true,
];
$config = array_merge($defaults, $options);
// 類型驗證
if (!$config['name'] || !$config['email']) {
throw new InvalidArgumentException('name 和 email 為必填');
}
return new User($config);
}
// 調用極其靈活,順序無關
createUser(['email' => 'a@b.com', 'name' => '張三']);
createUser(['name' => '李四', 'email' => 'c@d.com', 'role' => 'admin']);
<?php
class Calculator {
public function __call(string $name, array $args) {
if ($name !== 'calc') {
throw new BadMethodCallException("方法 $name 不存在");
}
return match (count($args)) {
0 => 0,
1 => $args[0],
2 => $this->binaryOp($args[0], $args[1]),
default => throw new BadFunctionCallException('calc 最多支援 2 參數'),
};
}
private function binaryOp($a, $b) {
return $a + $b; // 可擴展為策略模式
}
}
$calc = new Calculator();
echo $calc->calc(); // 0
echo $calc->calc(5); // 5
echo $calc->calc(3, 4); // 7
| 特性 | PHP 版本 | 適用場景 | 代碼示例 |
|---|---|---|---|
| 聯合類型 | 8.0+ | 參數類型多樣 | function foo(int|string $id) |
| 命名參數 | 8.0+ | 多可選參數、順序無關 | foo(name: 'a', age: 18) |
可變參數 ...$args | 5.6+ | 不定長參數列表 | function sum(int ...$nums) |
| 構造函數屬性提升 | 8.0+ | DTO/實體類快速定義 | class User { public function __construct(public string $name) {} } |
| 匹配表達式 match | 8.0+ | 嚴格類型分支 | match(count($args)) { 1 => ..., 2 => ... } |
<?php
class ApiClient {
public function request(
string $method,
string $url,
array $headers = [],
array $query = [],
?string $body = null,
int $timeout = 30,
bool $followRedirects = true
): Response {
// 實現...
}
}
$client = new ApiClient();
// 只傳必要參數,其餘用默認值,順序任意
$client->request(
method: 'POST',
url: '/api/users',
body: json_encode(['name' => '張三']),
timeout: 60,
headers: ['Authorization' => 'Bearer xxx']
);
User::fromArray()、User::fromJson()、User::fromRequest() (語義更清晰)createFromXxx() 語義明確PHP 的「重載」本質是運行時多態。現代 PHP 提供了更優雅、更安全、更可維護的原生特性,應優先採用命名參數、聯合類型、工廠模式等方案,將偽重載作為遺留代碼兼容或極少數動態場景的備選。