函数参数 #

一、位置参数 #

1.1 基本用法 #

php
<?php
function greet(string $name, int $age): string
{
    return "Hello, I'm $name, $age years old.";
}

echo greet("John", 25);

1.2 参数顺序 #

参数必须按定义顺序传递:

php
<?php
function createProfile(string $name, int $age, string $city): array
{
    return compact('name', 'age', 'city');
}

print_r(createProfile("John", 25, "Beijing"));

二、默认参数 #

2.1 基本用法 #

php
<?php
function greet(string $name = "Guest"): string
{
    return "Hello, $name!";
}

echo greet();
echo greet("John");

2.2 多个默认参数 #

php
<?php
function createConfig(
    string $host = "localhost",
    int $port = 3306,
    string $database = "test",
    string $charset = "utf8mb4"
): array {
    return compact('host', 'port', 'database', 'charset');
}

print_r(createConfig());
print_r(createConfig("127.0.0.1"));
print_r(createConfig("127.0.0.1", 3307, "mydb"));

2.3 默认参数位置规则 #

默认参数必须在非默认参数之后:

php
<?php
function valid(string $name, int $age = 18): array
{
    return compact('name', 'age');
}

function invalid(int $age = 18, string $name): array
{
    return compact('name', 'age');
}

2.4 null作为默认值 #

php
<?php
function process(?string $data = null): string
{
    return $data ?? "No data";
}

echo process();
echo process(null);
echo process("Hello");

三、命名参数(PHP 8.0+) #

3.1 基本用法 #

php
<?php
function createProfile(string $name, int $age, string $city): array
{
    return compact('name', 'age', 'city');
}

print_r(createProfile(
    name: "John",
    age: 25,
    city: "Beijing"
));

3.2 顺序无关 #

php
<?php
print_r(createProfile(
    city: "Shanghai",
    name: "Jane",
    age: 30
));

3.3 与位置参数混合 #

php
<?php
print_r(createProfile(
    "Bob",
    age: 35,
    city: "Guangzhou"
));

3.4 跳过默认参数 #

php
<?php
function createConfig(
    string $host = "localhost",
    int $port = 3306,
    string $database = "test"
): array {
    return compact('host', 'port', 'database');
}

print_r(createConfig(database: "mydb"));

3.5 内置函数使用命名参数 #

php
<?php
echo htmlspecialchars("<script>alert('xss')</script>", encoding: 'UTF-8');
echo number_format(1234.56, decimals: 2);

四、引用传递 #

4.1 基本用法 #

php
<?php
function increment(int &$value): void
{
    $value++;
}

$num = 5;
increment($num);
echo $num;

4.2 修改数组 #

php
<?php
function addItem(array &$arr, mixed $item): void
{
    $arr[] = $item;
}

$items = [1, 2, 3];
addItem($items, 4);
print_r($items);

4.3 交换变量 #

php
<?php
function swap(&$a, &$b): void
{
    $temp = $a;
    $a = $b;
    $b = $temp;
}

$x = 1;
$y = 2;
swap($x, $y);
echo "x = $x, y = $y";

4.4 注意事项 #

php
<?php
function addOne(int &$value): void
{
    $value++;
}

addOne(5);

五、可变参数 #

5.1 …运算符 #

php
<?php
function sum(int ...$numbers): int
{
    return array_sum($numbers);
}

echo sum(1, 2, 3, 4, 5);
echo sum(10, 20);
echo sum();

5.2 与固定参数混合 #

php
<?php
function format(string $prefix, string ...$items): string
{
    return $prefix . ": " . implode(", ", $items);
}

echo format("Items", "apple", "banana", "cherry");

5.3 类型声明 #

php
<?php
function process(string ...$strings): array
{
    return array_map('strtoupper', $strings);
}

print_r(process("hello", "world"));

5.4 展开数组 #

php
<?php
function sum(int ...$numbers): int
{
    return array_sum($numbers);
}

$arr = [1, 2, 3, 4, 5];
echo sum(...$arr);

5.5 func_get_args() #

PHP 5.5及之前版本:

php
<?php
function sum(): int
{
    return array_sum(func_get_args());
}

echo sum(1, 2, 3, 4, 5);

5.6 func_num_args()和func_get_arg() #

php
<?php
function getArguments(): array
{
    $count = func_num_args();
    $args = [];
    
    for ($i = 0; $i < $count; $i++) {
        $args[] = func_get_arg($i);
    }
    
    return $args;
}

print_r(getArguments('a', 'b', 'c'));

六、参数解构 #

6.1 数组解构 #

php
<?php
function processUser(array $user): string
{
    ['name' => $name, 'age' => $age] = $user;
    return "$name is $age years old";
}

echo processUser(['name' => 'John', 'age' => 25]);

6.2 在函数签名中使用 #

php
<?php
function processCoords(array $coords): float
{
    [$x, $y] = $coords;
    return sqrt($x ** 2 + $y ** 2);
}

echo processCoords([3, 4]);

七、参数验证 #

7.1 类型检查 #

php
<?php
declare(strict_types=1);

function process(int $id, string $name): void
{
    echo "Processing $id: $name";
}

process(1, "John");
process("1", "John");

7.2 手动验证 #

php
<?php
function createRange(int $start, int $end): array
{
    if ($start > $end) {
        throw new InvalidArgumentException("Start must be less than or equal to end");
    }
    
    return range($start, $end);
}

7.3 断言 #

php
<?php
function divide(float $a, float $b): float
{
    assert($b !== 0.0, "Divisor cannot be zero");
    return $a / $b;
}

八、参数默认值陷阱 #

8.1 表达式作为默认值 #

php
<?php
function logMessage(string $message, string $timestamp = date('Y-m-d H:i:s')): void
{
    echo "[$timestamp] $message\n";
}

function logMessage(string $message, ?string $timestamp = null): void
{
    $timestamp = $timestamp ?? date('Y-m-d H:i:s');
    echo "[$timestamp] $message\n";
}

8.2 数组作为默认值 #

php
<?php
function addItem(string $item, array $list = []): array
{
    $list[] = $item;
    return $list;
}

print_r(addItem("a"));
print_r(addItem("b"));

九、实际应用 #

9.1 配置函数 #

php
<?php
function createConnection(
    string $host = 'localhost',
    int $port = 3306,
    string $database = 'test',
    string $username = 'root',
    string $password = '',
    array $options = []
): PDO {
    $dsn = "mysql:host=$host;port=$port;dbname=$database";
    return new PDO($dsn, $username, $password, $options);
}

$db = createConnection(database: 'myapp');

9.2 日志函数 #

php
<?php
function log(
    string $message,
    string $level = 'INFO',
    ?string $channel = null,
    array $context = []
): void {
    $timestamp = date('Y-m-d H:i:s');
    $channel = $channel ?? 'default';
    $contextStr = empty($context) ? '' : ' ' . json_encode($context);
    
    echo "[$timestamp] [$channel] [$level] $message$contextStr\n";
}

log("User logged in");
log("Error occurred", "ERROR", "security");
log("Request processed", "DEBUG", context: ['duration' => 0.5]);

9.3 构建器模式 #

php
<?php
function buildQuery(
    string $table,
    array $columns = ['*'],
    array $where = [],
    ?string $orderBy = null,
    ?int $limit = null
): string {
    $columnsStr = implode(', ', $columns);
    $sql = "SELECT $columnsStr FROM $table";
    
    if (!empty($where)) {
        $conditions = [];
        foreach ($where as $column => $value) {
            $conditions[] = "$column = ?";
        }
        $sql .= " WHERE " . implode(' AND ', $conditions);
    }
    
    if ($orderBy !== null) {
        $sql .= " ORDER BY $orderBy";
    }
    
    if ($limit !== null) {
        $sql .= " LIMIT $limit";
    }
    
    return $sql;
}

echo buildQuery('users');
echo buildQuery('users', ['id', 'name'], ['status' => 'active'], 'created_at', 10);

十、最佳实践 #

10.1 参数数量控制 #

php
<?php
function process(array $config): void
{
    
}

process([
    'host' => 'localhost',
    'port' => 3306,
    'database' => 'test'
]);

10.2 使用命名参数提高可读性 #

php
<?php
sendEmail(
    to: 'user@example.com',
    subject: 'Welcome',
    body: 'Hello!',
    from: 'noreply@example.com'
);

10.3 避免布尔参数陷阱 #

php
<?php
function process(bool $flag): void {}

process(true);
process(flag: true);

10.4 使用对象代替多个参数 #

php
<?php
class EmailConfig
{
    public function __construct(
        public string $to,
        public string $subject,
        public string $body,
        public string $from = 'noreply@example.com',
        public array $attachments = []
    ) {}
}

function sendEmail(EmailConfig $config): bool
{
    
}

十一、总结 #

本章学习了:

  • 位置参数
  • 默认参数
  • 命名参数(PHP 8.0+)
  • 引用传递
  • 可变参数
  • 参数验证
  • 最佳实践

下一章将学习函数返回值。

最后更新:2026-03-26