PHP 变量作用域
PHP 变量拥有作用域 (Scope),这决定了在脚本的哪些地方可以访问或修改它们。每个变量都存在于一个特定的上下文中,除非明确声明,否则它的可用性将被严格限制在该上下文中。
1. 局部作用域 (Local Scope)
在函数内部声明的变量拥有局部作用域。这意味着它们只能从该特定函数的内部被访问。一旦函数执行完毕,这些局部变量就会被销毁。
拥有局部作用域的变量无法从声明它的函数外部被访问。如果你尝试从全局作用域访问局部变量,将会导致一个“未定义变量 (undefined variable)”的错误。
<?php
function greetUser() {
$message = "来自函数内部的问候!"; // $message 拥有局部作用域
echo $message;
}
greetUser(); // 调用函数,$message 被创建并使用
// 尝试在函数外部访问 $message 会导致错误
// echo $message; // 这行代码会引发一个 "Undefined variable: message" 错误
?>在上面的例子中,$message 是在 greetUser() 内部创建的,并且仅在该函数执行期间存在。不同的函数可以声明同名的变量而不会发生冲突,因为它们的作用域是完全隔离的。
<?php
function calculateSum($a, $b) {
$result = $a + $b; // $result 拥有局部作用域
return $result;
}
function displayGreeting($name) {
$greeting = "欢迎," . $name . "!"; // $greeting 拥有局部作用域
echo $greeting . "\n";
}
$sum = calculateSum(5, 10);
echo "总和是:" . $sum . "\n";
displayGreeting("爱丽丝");
// 尝试在这里访问 $result 或 $greeting 将会失败
// echo $result; // 错误
// echo $greeting; // 错误
?>calculateSum 中的参数 $a 和 $b 也是局部变量,充当传递给函数的实际值的占位符。
2. 全局作用域 (Global Scope)
在任何函数外部声明的变量拥有全局作用域。默认情况下,这些变量可以从脚本的任何地方被访问,唯独不能在函数内部直接访问。
要在函数内部访问全局变量,你必须使用 global 关键字显式声明它,或者通过 $GLOBALS 超全局数组来访问它。
2.1 使用 global 关键字
global 关键字向 PHP 明确指示:函数内部的这个变量应该引用全局版本的那个变量,而不是去创建一个新的局部变量。
<?php
$appName = "我的 PHP 应用"; // $appName 拥有全局作用域
$version = "1.0"; // $version 拥有全局作用域
function displayAppInfo() {
global $appName; // 声明此函数内的 $appName 引用的是全局的 $appName
global $version; // 声明此函数内的 $version 引用的是全局的 $version
echo "应用名称:" . $appName . "\n";
echo "版本:" . $version . "\n";
}
displayAppInfo();
// 输出:应用名称:我的 PHP 应用,版本:1.0
function updateVersion() {
global $version;
$version = "1.1"; // 修改了全局的 $version 变量
echo "函数内部更新后的版本:" . $version . "\n";
}
updateVersion();
// 输出:函数内部更新后的版本:1.1
echo "当前的全局版本:" . $version . "\n";
// 输出:当前的全局版本:1.1 (外部的变量确实被改变了)
?>使用 global 允许在函数内部对全局变量进行读取和写入操作。
2.2 使用 $GLOBALS 超全局数组
PHP 提供了一个名为 $GLOBALS 的特殊超全局数组。这个关联数组包含了在全局作用域中可用的所有变量的引用。变量名就是该数组的键 (Key)。
这种方法通常比 global 关键字更受青睐,因为它代码意图更清晰,并且能避免潜在的命名冲突。
<?php
$pageTitle = "产品列表"; // 全局变量
$itemsPerPage = 10; // 全局变量
function generateHeader() {
// 使用 $GLOBALS 数组访问全局变量
echo "<h1>" . $GLOBALS['pageTitle'] . "</h1>\n";
echo "<p>每页显示 " . $GLOBALS['itemsPerPage'] . " 个项目。</p>\n";
}
function updateItemsPerPage($newCount) {
// 使用 $GLOBALS 数组修改全局变量
$GLOBALS['itemsPerPage'] = $newCount;
echo "每页项目数已更新为:" . $GLOBALS['itemsPerPage'] . "\n";
}
generateHeader();
// 输出:
// <h1>产品列表</h1>
// <p>每页显示 10 个项目。</p>
updateItemsPerPage(20); // 全局修改了 $itemsPerPage
echo "更新后的全局 itemsPerPage:" . $itemsPerPage . "\n";
// 输出:更新后的全局 itemsPerPage:20
?>global $variable; 和 $GLOBALS['variable'] 都能达到在函数内部访问全局变量的目的。$GLOBALS 数组更加灵活,因为它允许使用字符串键动态地访问全局变量。
3. 静态作用域 (Static Scope)
static(静态)关键字应用于函数内部的局部变量。与函数执行完毕即被销毁的普通局部变量不同,静态变量在同一个函数的多次调用之间会保留它们最后的值。
它们只在脚本执行期间被初始化一次(也就是函数第一次被调用时)。
<?php
function trackVisits() {
static $counter = 0; // $counter 是一个静态变量
$counter++;
echo "页面访问量:" . $counter . "\n";
}
trackVisits(); // 输出:页面访问量:1
trackVisits(); // 输出:页面访问量:2
trackVisits(); // 输出:页面访问量:3
// 静态变量 $counter 在函数外部是无法访问的
// echo $counter; // 这会导致 "Undefined variable: counter" 错误
?>在 trackVisits() 的例子中,$counter 只被初始化为 0 一次。在随后的调用中,它记住了自己之前的值(1,然后是 2),并在此基础上递增。如果 $counter 只是一个普通的局部变量,它在每次函数调用时都会被重新初始化为 0,那么输出将永远是“页面访问量:1”。
静态变量非常适合用于在函数内部维护状态,而无需诉诸于全局变量或在函数内外来回传递值。
<?php
function generateUniqueId() {
static $lastId = 1000; // 初始化一个基础 ID
$lastId++;
return "USER_" . $lastId;
}
echo generateUniqueId() . "\n"; // 输出:USER_1001
echo generateUniqueId() . "\n"; // 输出:USER_1002
echo generateUniqueId() . "\n"; // 输出:USER_1003
?>在这里,generateUniqueId() 使用了静态变量 $lastId 来确保每个生成的 ID 都是唯一且递增的。