变量作用域

变量作用域决定了在程序的哪些地方可以访问到特定的变量。理解作用域对于编写正确、安全的函数至关重要。

什么是变量作用域?

变量作用域是指变量在代码中可被访问的范围。PHP中有几种主要的作用域:

  1. 局部作用域(Local Scope):函数内部
  2. 全局作用域(Global Scope):函数外部
  3. 静态作用域(Static Scope):函数内部但保持值的持久性
  4. 超全局作用域(Superglobal Scope):特殊的全局变量

局部作用域

在函数内部声明的变量具有局部作用域,只能在函数内部访问。

基本局部变量

<?php
function testFunction() {
    $localVariable = "这是一个局部变量";
    echo "函数内部:$localVariable<br>";
}

testFunction();

// 错误:无法在函数外部访问局部变量
// echo $localVariable;  // 会报错:Undefined variable
?>

局部变量的隔离性

<?php
// 函数1中的局部变量
function function1() {
    $name = "张三";
    echo "函数1中的姓名:$name<br>";
}

// 函数2中的局部变量
function function2() {
    $name = "李四";  // 这是一个完全不同的变量
    echo "函数2中的姓名:$name<br>";
}

// 全局变量
$name = "王五";

function function3() {
    $name = "赵六";  // 这也是局部变量,与全局变量无关
    echo "函数3中的姓名:$name<br>";
}

function1();  // 输出:张三
function2();  // 输出:李四
function3();  // 输出:赵六

echo "全局变量中的姓名:$name<br>";  // 输出:王五
?>

局部变量的生命周期

<?php
function counter() {
    $count = 0;  // 每次调用都会重新创建
    $count++;
    echo "计数器的值:$count<br>";
}

echo "第一次调用:<br>";
counter();  // 输出:1

echo "第二次调用:<br>";
counter();  // 输出:1(重新开始,因为$count是局部变量)

echo "第三次调用:<br>";
counter();  // 输出:1
?>

全局作用域

在函数外部声明的变量具有全局作用域,可以在脚本的任何地方访问(除了函数内部)。

全局变量示例

<?php
$globalVariable = "这是一个全局变量";

function showGlobalVariable() {
    // 错误:不能直接在函数内部访问全局变量
    // echo $globalVariable;
}

// 正确:在函数外部可以访问
echo "函数外部:$globalVariable<br>";
?>

使用 global 关键字

要在函数内部访问全局变量,需要使用 global 关键字。

<?php
$globalCounter = 0;

function incrementCounter() {
    global $globalCounter;  // 声明要使用全局变量
    $globalCounter++;
    echo "计数器值:$globalCounter<br>";
}

function resetCounter() {
    global $globalCounter;
    $globalCounter = 0;
    echo "计数器已重置<br>";
}

echo "初始值:$globalCounter<br>";

incrementCounter();  // 输出:1
incrementCounter();  // 输出:2

echo "当前值:$globalCounter<br>";

resetCounter();
echo "重置后:$globalCounter<br>";
?>

使用 $GLOBALS 数组

PHP还提供了 $GLOBALS 超全局数组来访问全局变量。

<?php
$config = [
    'database_host' => 'localhost',
    'database_name' => 'myapp',
    'debug_mode' => true
];

function showConfig() {
    // 使用$GLOBALS访问全局变量
    echo "数据库主机:" . $GLOBALS['config']['database_host'] . "<br>";
    echo "数据库名称:" . $GLOBALS['config']['database_name'] . "<br>";
}

function toggleDebugMode() {
    // 修改全局变量
    $GLOBALS['config']['debug_mode'] = !$GLOBALS['config']['debug_mode'];
    echo "调试模式已" . ($GLOBALS['config']['debug_mode'] ? "开启" : "关闭") . "<br>";
}

showConfig();
echo "当前调试模式:" . ($config['debug_mode'] ? "开启" : "关闭") . "<br>";

toggleDebugMode();
echo "切换后调试模式:" . ($config['debug_mode'] ? "开启" : "关闭") . "<br>";
?>

global vs $GLOBALS 的区别

<?php
$var1 = "原始值1";
$var2 = "原始值2";

function testGlobal() {
    global $var1;        // 引用全局变量
    $var1 = "修改值1";   // 修改的是全局变量
}

function testGlobals() {
    $GLOBALS['var2'] = "修改值2";  // 直接修改全局变量
}

echo "修改前:<br>";
echo "var1: $var1<br>";
echo "var2: $var2<br>";

testGlobal();
testGlobals();

echo "修改后:<br>";
echo "var1: $var1<br>";
echo "var2: $var2<br>";
?>

静态作用域

静态变量在函数调用之间保持其值,但只能在函数内部访问。

基本静态变量

<?php
function staticCounter() {
    static $counter = 0;  // 静态变量,只初始化一次
    $counter++;
    echo "静态计数器值:$counter<br>";
}

function normalCounter() {
    $counter = 0;  // 普通局部变量,每次调用都重新初始化
    $counter++;
    echo "普通计数器值:$counter<br>";
}

echo "静态计数器测试:<br>";
staticCounter();  // 输出:1
staticCounter();  // 输出:2
staticCounter();  // 输出:3

echo "<br>普通计数器测试:<br>";
normalCounter();  // 输出:1
normalCounter();  // 输出:1
normalCounter();  // 输出:1
?>

静态变量的实际应用

<?php
// 数据库连接池示例
function getDatabaseConnection() {
    static $connection = null;  // 静态变量保持连接

    if ($connection === null) {
        echo "创建新的数据库连接...<br>";
        // 模拟创建数据库连接
        $connection = [
            'host' => 'localhost',
            'database' => 'myapp',
            'connection_id' => uniqid('conn_'),
            'created_at' => date('Y-m-d H:i:s')
        ];
    } else {
        echo "使用现有的数据库连接...<br>";
    }

    return $connection;
}

function closeDatabaseConnection() {
    static $connection = null;  // 这是不同的静态变量
    // 注意:这个函数无法访问 getDatabaseConnection 中的静态变量
    echo "关闭数据库连接功能需要单独实现<br>";
}

// 多次调用连接函数
echo "第一次连接请求:<br>";
$conn1 = getDatabaseConnection();
echo "连接ID:" . $conn1['connection_id'] . "<br>";

echo "<br>第二次连接请求:<br>";
$conn2 = getDatabaseConnection();
echo "连接ID:" . $conn2['connection_id'] . "<br>";

echo "<br>第三次连接请求:<br>";
$conn3 = getDatabaseConnection();
echo "连接ID:" . $conn3['connection_id'] . "<br>";

echo "可以看到三次都使用了同一个连接<br>";
?>

静态变量的高级用法

<?php
// 缓存函数结果
function expensiveCalculation($input) {
    static $cache = [];  // 静态缓存数组

    // 检查缓存中是否已有结果
    if (isset($cache[$input])) {
        echo "从缓存获取结果...<br>";
        return $cache[$input];
    }

    echo "执行复杂计算...<br>";
    // 模拟复杂计算
    $result = $input * $input + sqrt($input);

    // 存入缓存
    $cache[$input] = $result;

    return $result;
}

// 测试缓存效果
echo "计算 5:<br>";
$result1 = expensiveCalculation(5);
echo "结果:$result1<br>";

echo "<br>再次计算 5:<br>";
$result2 = expensiveCalculation(5);
echo "结果:$result2<br>";

echo "<br>计算 10:<br>";
$result3 = expensiveCalculation(10);
echo "结果:$result3<br>";

echo "<br>再次计算 10:<br>";
$result4 = expensiveCalculation(10);
echo "结果:$result4<br>";
?>

超全局变量

PHP提供了一些特殊的超全局变量,它们在任何作用域中都可以访问。

常见的超全局变量

<?php
function showSuperglobals() {
    echo "=== 超全局变量示例 ===<br>";

    // $_GET - GET请求参数
    echo "\$_GET 示例:<br>";
    if (isset($_GET['name'])) {
        echo "GET参数name:{$_GET['name']}<br>";
    } else {
        echo "没有GET参数<br>";
    }

    // $_POST - POST请求参数
    echo "\$_POST 示例:<br>";
    if (isset($_POST['email'])) {
        echo "POST参数email:{$_POST['email']}<br>";
    } else {
        echo "没有POST参数<br>";
    }

    // $_SERVER - 服务器和环境信息
    echo "\$_SERVER 示例:<br>";
    echo "PHP版本:" . $_SERVER['PHP_SELF'] . "<br>";
    echo "服务器软件:" . $_SERVER['SERVER_SOFTWARE'] . "<br>";
    echo "请求时间:" . date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) . "<br>";

    // $_ENV - 环境变量
    echo "\$_ENV 示例:<br>";
    echo "操作系统:" . ($_ENV['OS'] ?? '未知') . "<br>";

    // $_COOKIE - Cookie数据
    echo "\$_COOKIE 示例:<br>";
    if (!empty($_COOKIE)) {
        foreach ($_COOKIE as $name => $value) {
            echo "Cookie $name: $value<br>";
        }
    } else {
        echo "没有Cookie数据<br>";
    }

    // $_SESSION - Session数据(需要先启动session)
    echo "\$_SESSION 示例:<br>";
    if (session_status() == PHP_SESSION_NONE) {
        session_start();
    }
    $_SESSION['last_visit'] = date('Y-m-d H:i:s');
    echo "最后访问时间:" . $_SESSION['last_visit'] . "<br>";

    // $_FILES - 上传文件信息
    echo "\$_FILES 示例:<br>";
    if (!empty($_FILES)) {
        foreach ($_FILES as $fieldName => $fileInfo) {
            echo "上传文件 $fieldName: {$fileInfo['name']}<br>";
        }
    } else {
        echo "没有上传文件<br>";
    }

    // $GLOBALS - 所有全局变量的引用
    echo "\$GLOBALS 示例:<br>";
    echo "全局变量数量:" . count($GLOBALS) . "<br>";
}

// 测试超全局变量
showSuperglobals();
?>

实际应用示例

配置管理器

<?php
class ConfigManager {
    // 全局配置数组
    private static $globalConfig = [
        'database' => [
            'host' => 'localhost',
            'port' => 3306,
            'charset' => 'utf8mb4'
        ],
        'app' => [
            'name' => 'MyApp',
            'version' => '1.0.0',
            'debug' => false
        ]
    ];

    // 获取配置
    public static function get($key, $default = null) {
        $keys = explode('.', $key);
        $config = self::$globalConfig;

        foreach ($keys as $k) {
            if (!isset($config[$k])) {
                return $default;
            }
            $config = $config[$k];
        }

        return $config;
    }

    // 设置配置
    public static function set($key, $value) {
        $keys = explode('.', $key);
        $config = &self::$globalConfig;

        for ($i = 0; $i < count($keys) - 1; $i++) {
            if (!isset($config[$keys[$i]])) {
                $config[$keys[$i]] = [];
            }
            $config = &$config[$keys[$i]];
        }

        $config[$keys[count($keys) - 1]] = $value;
        return true;
    }
}

// 数据库连接函数使用全局配置
function connectToDatabase() {
    $host = ConfigManager::get('database.host', 'localhost');
    $port = ConfigManager::get('database.port', 3306);
    $charset = ConfigManager::get('database.charset', 'utf8mb4');

    echo "连接数据库:$host:$port (字符集: $charset)<br>";

    // 模拟返回连接对象
    return [
        'host' => $host,
        'port' => $port,
        'charset' => $charset,
        'connection_id' => uniqid('db_')
    ];
}

// 应用初始化函数
function initializeApp() {
    $appName = ConfigManager::get('app.name', 'Unknown App');
    $version = ConfigManager::get('app.version', '0.0.0');
    $debug = ConfigManager::get('app.debug', false);

    echo "启动应用:$appName v$version<br>";
    echo "调试模式:" . ($debug ? '开启' : '关闭') . "<br>";

    if ($debug) {
        echo "警告:调试模式在生产环境中应关闭!<br>";
    }

    return true;
}

// 使用配置管理器
echo "=== 配置管理器示例 ===<br>";

// 初始化应用
initializeApp();

// 连接数据库
$dbConnection = connectToDatabase();
echo "数据库连接ID:" . $dbConnection['connection_id'] . "<br>";

// 动态修改配置
ConfigManager::set('app.debug', true);
echo "<br>修改调试模式后重新初始化:<br>";
initializeApp();
?>

用户认证系统

<?php
// 用户认证系统
class AuthSystem {
    // 使用静态变量模拟用户会话
    private static $currentUser = null;
    private static $loginAttempts = 0;
    private static $maxLoginAttempts = 3;

    // 用户登录
    public static function login($username, $password) {
        // 模拟用户数据库
        $users = [
            'admin' => ['password' => 'admin123', 'role' => 'admin'],
            'user' => ['password' => 'user123', 'role' => 'user'],
            'guest' => ['password' => 'guest123', 'role' => 'guest']
        ];

        if (!isset($users[$username])) {
            self::$loginAttempts++;
            return ['success' => false, 'message' => '用户名不存在'];
        }

        if ($users[$username]['password'] !== $password) {
            self::$loginAttempts++;
            return ['success' => false, 'message' => '密码错误'];
        }

        if (self::$loginAttempts >= self::$maxLoginAttempts) {
            return ['success' => false, 'message' => '登录尝试次数过多,请稍后再试'];
        }

        // 登录成功
        self::$currentUser = [
            'username' => $username,
            'role' => $users[$username]['role'],
            'login_time' => date('Y-m-d H:i:s'),
            'session_id' => uniqid('sess_')
        ];

        self::$loginAttempts = 0;  // 重置登录尝试次数

        return ['success' => true, 'user' => self::$currentUser];
    }

    // 用户登出
    public static function logout() {
        if (self::$currentUser !== null) {
            $username = self::$currentUser['username'];
            self::$currentUser = null;
            return ['success' => true, 'message' => "用户 $username 已登出"];
        }
        return ['success' => false, 'message' => '没有用户登录'];
    }

    // 获取当前用户
    public static function getCurrentUser() {
        return self::$currentUser;
    }

    // 检查是否已登录
    public static function isLoggedIn() {
        return self::$currentUser !== null;
    }

    // 检查用户权限
    public static function hasPermission($requiredRole) {
        if (!self::isLoggedIn()) {
            return false;
        }

        $roleHierarchy = [
            'guest' => 0,
            'user' => 1,
            'admin' => 2
        ];

        $userRole = self::$currentUser['role'];
        $userLevel = $roleHierarchy[$userLevel] ?? 0;
        $requiredLevel = $roleHierarchy[$requiredRole] ?? 0;

        return $userLevel >= $requiredLevel;
    }

    // 获取登录状态信息
    public static function getAuthStatus() {
        return [
            'is_logged_in' => self::isLoggedIn(),
            'current_user' => self::$currentUser,
            'login_attempts' => self::$loginAttempts,
            'max_attempts' => self::$maxLoginAttempts
        ];
    }
}

// 权限检查函数
function requireLogin() {
    if (!AuthSystem::isLoggedIn()) {
        echo "错误:需要登录才能访问此功能<br>";
        return false;
    }
    return true;
}

function requireRole($role) {
    if (!requireLogin()) {
        return false;
    }

    if (!AuthSystem::hasPermission($role)) {
        echo "错误:需要 $role 权限才能访问此功能<br>";
        return false;
    }
    return true;
}

// 示例:管理面板
function adminPanel() {
    if (!requireRole('admin')) {
        return;
    }

    $user = AuthSystem::getCurrentUser();
    echo "欢迎访问管理面板,{$user['username']}!<br>";
    echo "登录时间:{$user['login_time']}<br>";
    echo "会话ID:{$user['session_id']}<br>";
}

// 示例:用户面板
function userPanel() {
    if (!requireRole('user')) {
        return;
    }

    $user = AuthSystem::getCurrentUser();
    echo "欢迎访问用户面板,{$user['username']}!<br>";
    echo "您的角色:{$user['role']}<br>";
}

// 测试认证系统
echo "=== 用户认证系统示例 ===<br>";

// 测试登录
echo "<br>尝试登录:<br>";
$loginResult = AuthSystem::login('admin', 'admin123');
if ($loginResult['success']) {
    echo "登录成功!用户:{$loginResult['user']['username']}<br>";
} else {
    echo "登录失败:" . $loginResult['message'] . "<br>";
}

// 访问用户面板
echo "<br>访问用户面板:<br>";
userPanel();

// 访问管理面板
echo "<br>访问管理面板:<br>";
adminPanel();

// 测试权限
echo "<br>权限测试:<br>";
echo "是否有guest权限:" . (AuthSystem::hasPermission('guest') ? '是' : '否') . "<br>";
echo "是否有user权限:" . (AuthSystem::hasPermission('user') ? '是' : '否') . "<br>";
echo "是否有admin权限:" . (AuthSystem::hasPermission('admin') ? '是' : '否') . "<br>";

// 登出
echo "<br>用户登出:<br>";
$logoutResult = AuthSystem::logout();
echo $logoutResult['message'] . "<br>";

// 再次尝试访问面板
echo "<br>登出后访问用户面板:<br>";
userPanel();
?>

函数调用计数器

<?php
// 函数调用计数器和性能监控
function expensiveOperation($input) {
    // 静态变量用于统计
    static $callCount = 0;
    static $totalTime = 0;
    static $inputHistory = [];

    $startTime = microtime(true);

    // 执行实际操作
    $result = performCalculation($input);

    $endTime = microtime(true);
    $executionTime = ($endTime - $startTime) * 1000; // 转换为毫秒

    // 更新统计信息
    $callCount++;
    $totalTime += $executionTime;
    $inputHistory[] = [
        'input' => $input,
        'time' => $executionTime,
        'timestamp' => date('Y-m-d H:i:s')
    ];

    // 保持最近10次的历史记录
    if (count($inputHistory) > 10) {
        array_shift($inputHistory);
    }

    // 输出统计信息
    echo "第 $callCount 次调用,执行时间:" . number_format($executionTime, 4) . "ms<br>";

    return $result;
}

function performCalculation($input) {
    // 模拟复杂计算
    usleep(rand(10000, 100000)); // 随机延迟10-100毫秒
    return $input * $input + sqrt(abs($input));
}

// 获取性能统计
function getPerformanceStats() {
    // 这里我们无法直接访问 expensiveOperation 中的静态变量
    // 这是一个限制:静态变量只能在声明它们的函数中访问
    echo "注意:静态变量只能在其声明的函数内部访问<br>";
    echo "要获取性能统计,需要在函数内部提供专门的访问方法<br>";
}

// 性能监控类(更好的解决方案)
class PerformanceMonitor {
    private static $stats = [
        'function_calls' => [],
        'total_calls' => 0
    ];

    public static function trackCall($functionName, $input, $result, $executionTime) {
        if (!isset(self::$stats['function_calls'][$functionName])) {
            self::$stats['function_calls'][$functionName] = [
                'count' => 0,
                'total_time' => 0,
                'avg_time' => 0,
                'min_time' => PHP_FLOAT_MAX,
                'max_time' => 0,
                'recent_calls' => []
            ];
        }

        $funcStats = &self::$stats['function_calls'][$functionName];
        $funcStats['count']++;
        $funcStats['total_time'] += $executionTime;
        $funcStats['avg_time'] = $funcStats['total_time'] / $funcStats['count'];
        $funcStats['min_time'] = min($funcStats['min_time'], $executionTime);
        $funcStats['max_time'] = max($funcStats['max_time'], $executionTime);

        $funcStats['recent_calls'][] = [
            'input' => $input,
            'result' => $result,
            'time' => $executionTime,
            'timestamp' => date('Y-m-d H:i:s')
        ];

        // 保持最近5次调用
        if (count($funcStats['recent_calls']) > 5) {
            array_shift($funcStats['recent_calls']);
        }

        self::$stats['total_calls']++;
    }

    public static function getStats($functionName = null) {
        if ($functionName) {
            return self::$stats['function_calls'][$functionName] ?? null;
        }
        return self::$stats;
    }

    public static function printReport() {
        echo "=== 性能统计报告 ===<br>";
        echo "总函数调用次数:" . self::$stats['total_calls'] . "<br>";
        echo "<br>";

        foreach (self::$stats['function_calls'] as $funcName => $stats) {
            echo "函数:$funcName<br>";
            echo "- 调用次数:" . $stats['count'] . "<br>";
            echo "- 平均执行时间:" . number_format($stats['avg_time'] * 1000, 4) . "ms<br>";
            echo "- 最短执行时间:" . number_format($stats['min_time'] * 1000, 4) . "ms<br>";
            echo "- 最长执行时间:" . number_format($stats['max_time'] * 1000, 4) . "ms<br>";
            echo "<br>";
        }
    }
}

// 带性能监控的函数
function monitoredExpensiveOperation($input) {
    $startTime = microtime(true);

    // 执行实际操作
    $result = performCalculation($input);

    $endTime = microtime(true);
    $executionTime = $endTime - $startTime;

    // 记录性能数据
    PerformanceMonitor::trackCall('monitoredExpensiveOperation', $input, $result, $executionTime);

    return $result;
}

// 测试性能监控
echo "=== 性能监控示例 ===<br>";

// 执行多次调用
for ($i = 1; $i <= 5; $i++) {
    echo "第 $i 次调用:";
    $result = monitoredExpensiveOperation($i * 10);
    echo "结果:" . number_format($result, 2) . "<br>";
}

// 显示性能报告
PerformanceMonitor::printReport();
?>

最佳实践

1. 避免过度使用全局变量

<?php
// 不好的做法:大量使用全局变量
$database_host = 'localhost';
$database_name = 'myapp';
$database_user = 'admin';
$database_pass = 'password';

function connectDB() {
    global $database_host, $database_name, $database_user, $database_pass;
    // 连接数据库...
}

// 好的做法:使用配置类或静态变量
class DatabaseConfig {
    private static $config = [
        'host' => 'localhost',
        'name' => 'myapp',
        'user' => 'admin',
        'password' => 'password'
    ];

    public static function get($key) {
        return self::$config[$key] ?? null;
    }
}

function connectDBBetter() {
    $host = DatabaseConfig::get('host');
    $name = DatabaseConfig::get('name');
    // 连接数据库...
}
?>

2. 合理使用静态变量

<?php
// 好的做法:使用静态变量实现缓存
function getCachedData($key) {
    static $cache = [];
    static $cacheTimeout = 300; // 5分钟

    $now = time();

    // 检查缓存是否存在且未过期
    if (isset($cache[$key]) && ($now - $cache[$key]['timestamp']) < $cacheTimeout) {
        return $cache[$key]['data'];
    }

    // 获取新数据(模拟)
    $data = fetchFromDatabase($key);

    // 存入缓存
    $cache[$key] = [
        'data' => $data,
        'timestamp' => $now
    ];

    return $data;
}

function fetchFromDatabase($key) {
    // 模拟数据库查询
    return "数据_$key_" . date('Y-m-d H:i:s');
}
?>

3. 明确变量的作用域

<?php
// 好的做法:明确声明全局变量
function processData() {
    global $logger;  // 明确声明使用全局变量
    $logger->log('开始处理数据');

    // 处理逻辑...

    $logger->log('数据处理完成');
}

// 更好的做法:通过参数传递
function processDataBetter(Logger $logger) {
    $logger->log('开始处理数据');

    // 处理逻辑...

    $logger->log('数据处理完成');
}
?>

常见错误和解决方案

1. 函数内部访问全局变量失败

<?php
// 错误示例
$config = ['debug' => true];

function debugMode() {
    if ($config['debug']) {  // 错误:无法访问全局变量
        echo "调试模式开启";
    }
}

// 解决方案1:使用global关键字
function debugModeFixed1() {
    global $config;
    if ($config['debug']) {
        echo "调试模式开启";
    }
}

// 解决方案2:使用$GLOBALS
function debugModeFixed2() {
    if ($GLOBALS['config']['debug']) {
        echo "调试模式开启";
    }
}

// 解决方案3:通过参数传递(推荐)
function debugModeFixed3($config) {
    if ($config['debug']) {
        echo "调试模式开启";
    }
}
?>

2. 静态变量初始化问题

<?php
// 错误:静态变量不能使用表达式初始化
function badExample() {
    // static $config = getConfig();  // 错误
    // static $time = time();         // 错误
}

// 正确做法
function goodExample() {
    static $config = null;
    static $initialized = false;

    if (!$initialized) {
        $config = getConfig();  // 延迟初始化
        $initialized = true;
    }

    return $config;
}

function getConfig() {
    return ['debug' => true];
}
?>

3. 变量作用域混淆

<?php
$name = '全局变量';

function testScope() {
    $name = '局部变量';
    echo "函数内部:$name<br>";  // 输出:局部变量
}

testScope();
echo "函数外部:$name<br>";  // 输出:全局变量

// 使用global关键字修改全局变量
function modifyGlobal() {
    global $name;
    $name = '修改后的全局变量';
}

modifyGlobal();
echo "修改后:$name<br>";  // 输出:修改后的全局变量
?>

练习题

基础练习

  1. 变量作用域测试

    <?php
    $globalVar = "全局变量";
    
    function testScope() {
        $localVar = "局部变量";
        // 尝试访问和修改全局变量
        // 输出不同作用域的变量
    }
    
    // 你的代码
    
    testScope();
    ?>
    
  2. 静态计数器

    <?php
    // 创建一个函数,使用静态变量记录调用次数
    function callCounter() {
        // 你的代码
    }
    
    // 测试多次调用
    ?>
    
  3. 全局变量访问

    <?php
    $config = ['app_name' => 'MyApp', 'version' => '1.0'];
    
    function getConfig($key) {
        // 使用global或$GLOBALS访问全局配置
        // 你的代码
    }
    
    echo getConfig('app_name');
    ?>
    

进阶练习

  1. 缓存系统

    <?php
    class SimpleCache {
        // 使用静态变量实现缓存
        public static function get($key) {
            // 你的代码
        }
    
        public static function set($key, $value, $ttl = 3600) {
            // 你的代码
        }
    }
    
    // 测试缓存功能
    ?>
    
  2. 配置管理器

    <?php
    class Config {
        private static $config = [];
    
        public static function load($file) {
            // 从文件加载配置
        }
    
        public static function get($key, $default = null) {
            // 获取配置值
        }
    
        public static function set($key, $value) {
            // 设置配置值
        }
    }
    
    // 实现配置管理器
    ?>
    

实战练习

  1. 用户会话管理

    <?php
    class SessionManager {
        private static $session = [];
    
        public static function login($username, $password) {
            // 实现登录逻辑
        }
    
        public static function logout() {
            // 实现登出逻辑
        }
    
        public static function isLoggedIn() {
            // 检查登录状态
        }
    
        public static function getCurrentUser() {
            // 获取当前用户
        }
    }
    
    // 创建完整的会话管理系统
    ?>
    
  2. 性能监控器

    <?php
    class PerformanceProfiler {
        private static $profiles = [];
    
        public static function start($name) {
            // 开始性能分析
        }
    
        public static function end($name) {
            // 结束性能分析
        }
    
        public static function getReport() {
            // 生成性能报告
        }
    }
    
    // 创建性能分析器并测试
    ?>
    

总结

变量作用域是PHP编程中的重要概念,掌握不同作用域的特点和使用方法对于编写高质量的代码至关重要。通过本章的学习,你应该能够:

  1. 理解局部、全局、静态作用域的区别
  2. 正确使用 global 关键字和 $GLOBALS 数组
  3. 合理运用静态变量实现缓存和状态保持
  4. 了解超全局变量的使用场景
  5. 避免常见的变量作用域错误
  6. 在实际项目中应用最佳实践

记住,合理使用变量作用域可以让代码更加清晰、安全和可维护。在实际开发中,要尽量避免过度使用全局变量,优先考虑参数传递和静态变量的使用。

下一章我们将学习PHP内置函数,了解如何利用PHP提供的强大函数库来提高开发效率。