想让函数A的数据顺利“串门”到函数B?很多PHPer新手都在参数传递这个路口绕晕过!今天咱们就来把值传递、引用传递、默认参数、类型声明这些“交通规则”一次性讲明白,保证让你的数据像顺丰快递一样精准送达,绝不“丢包”!
🚀 第一章:参数传递——PHP函数的“对话艺术”
1.1 从一个尴尬场景说起
想象一下这个场景:你写了个函数给用户发红包:
function sendBonus($money, $user) {
$money = 0; // 红包发完了
echo "给{$user}发了红包!";
}
$myMoney = 100;
$user = "张三";
sendBonus($myMoney, $user);
echo "我的余额:{$myMoney}元"; // 猜猜这里输出多少?
运行后你会发现:我的余额:100元!
什么情况?明明函数里把money设为了0,为什么外面的myMoney还是100?
恭喜你,遇到了PHP参数传递的第一个核心概念——值传递(Pass by Value)。
1.2 值传递:复印店老板的哲学
值传递就像去复印店:
- 你把原稿给老板(调用函数传参数)
- 老板复印一份(PHP创建参数的副本)
- 他在复印件上随便涂改(函数内修改参数)
- 你的原稿毫发无损(原始变量不变)
// 值传递的经典例子
function addPrefix($string) {
$string = "PHP大神:" . $string;
return $string;
}
$name = "小明的代码";
echo addPrefix($name); // 输出:PHP大神:小明的代码
echo $name; // 输出:小明的代码(原值没变!)
90%的PHP函数调用都是值传递,这是默认行为,安全可靠,避免了“副作用”。
🔗 第二章:引用传递——共享同一个“实物”
2.1 什么时候需要引用传递?
但有时候,我们确实需要函数直接修改原始数据。比如:
// 场景:直接修改用户余额
function rechargeWallet(&$balance, $amount) {
$balance += $amount; // 直接修改原变量
}
$myBalance = 50;
rechargeWallet($myBalance, 100);
echo $myBalance; // 输出:150!原值被修改了
看到那个&$balance了吗?这个&符号就是**引用传递(Pass by Reference)**的魔法标记!
2.2 引用传递像什么?合租室友的冰箱
如果说值传递是复印文件,那引用传递就是合租时共用的冰箱:
// 合租冰箱比喻
$refrigerator = ["鸡蛋" => 5, "牛奶" => 1]; // 公共冰箱
function roomMateEats(&$fridge, $food) {
if (isset($fridge[$food]) && $fridge[$food] > 0) {
$fridge[$food]--; // 直接减少冰箱里的食物
echo "吃了一个{$food},还剩{$fridge[$food]}个\n";
}
}
// 室友A吃了鸡蛋
roomMateEats($refrigerator, "鸡蛋");
// 室友B看到的冰箱
print_r($refrigerator); // 鸡蛋只剩4个了!两人操作的是同一个冰箱
关键区别:
- 值传递:
function foo($var)→ 操作副本 - 引用传递:
function foo(&$var)→ 操作原变量
2.3 引用传递的典型应用场景
场景1:交换两个变量的值
function swap(&$a, &$b) {
$temp = $a;
$a = $b;
$b = $temp;
}
$x = 10;
$y = 20;
swap($x, $y);
echo "x={$x}, y={$y}"; // x=20, y=10 完美交换!
场景2:批量处理数组
function addScoreToAll(&$students) {
foreach ($students as &$student) {
$student['score'] += 10; // 给所有人加10分
}
}
$class = [
["name" => "小明", "score" => 70],
["name" => "小红", "score" => 85]
];
addScoreToAll($class);
print_r($class); // 所有人的score都加了10分
⚠️ 第三章:引用传递的“深水区”与陷阱
3.1 循环中的引用“留坑”问题
看这个经典bug:
$values = [1, 2, 3];
$array = [];
foreach ($values as &$value) {
$array[] = $value;
}
// 你以为$value现在没用了?不!
$value = 100;
print_r($array);
// 你期望:[1, 2, 3]
// 实际输出:[1, 2, 100] ← 最后一个元素被改了!
为什么? 因为$value在循环结束后仍然引用着$values[2]!
解决方案:
foreach ($values as &$value) {
// 处理逻辑
}
unset($value); // 循环后立即释放引用!
3.2 函数返回引用(高级技巧)
PHP还允许函数返回引用,但要用对地方:
class Config {
private $settings = [];
public function &get($key) {
if (!isset($this->settings[$key])) {
$this->settings[$key] = null;
}
return $this->settings[$key]; // 返回引用
}
}
$config = new Config();
$theme = &$config->get('theme');
$theme = 'dark'; // 直接修改了类的私有属性!
// 对比非引用版本
class Config2 {
// ... 类似
public function get($key) {
return $this->settings[$key] ?? null; // 返回值
}
}
$config2 = new Config2();
$theme2 = $config2->get('theme');
$theme2 = 'dark'; // 只修改了$theme2,不影响类内部
经验法则:除非你在写框架或库,否则普通业务代码慎用返回引用!
🎛️ 第四章:更多参数传递“黑科技”
4.1 默认参数:给参数上“保险”
// 基础版
function orderCoffee($type = "美式", $size = "中杯") {
return "您的{$size}{$type}咖啡好了!";
}
echo orderCoffee(); // "您的中杯美式咖啡好了!"
echo orderCoffee("拿铁", "大杯"); // "您的大杯拿铁咖啡好了!"
// 重要规则:默认参数必须放后面!
function rightWay($required, $optional = "default") { /* 正确 */ }
// function wrongWay($optional = "default", $required) { /* 语法错误! */ }
4.2 类型声明:PHP的“安检系统”
PHP 7+ 引入了严格类型检查:

最低0.47元/天 解锁文章
1728

被折叠的 条评论
为什么被折叠?



