函数参数 #
一、位置参数 #
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