Skip to content

变量和常量

概述

变量和常量是PHP中的基本构建块。本章涵盖变量声明、作用域、生命周期、超全局变量、常量,以及在PHP应用程序中管理数据的最佳实践。

变量

变量基础

声明和赋值

php
<?php
// 变量声明和赋值
$name = "John Doe";
$age = 30;
$salary = 50000.50;
$isActive = true;

// 多重赋值
$a = $b = $c = 10;

// 变量引用赋值
$original = "Hello";
$reference = &$original;
$reference = "World";
echo $original; // "World"(因为引用而改变)
?>

变量命名规则

php
<?php
// 有效的变量名
$userName = "john";
$user_name = "jane";
$_private = "hidden";
$user2 = "second user";
$HTML = "<h1>Title</h1>";

// 无效的变量名(会导致错误)
// $2user = "error";      // 不能以数字开头
// $user-name = "error";  // 不能包含连字符
// $user name = "error";  // 不能包含空格
// $class = "error";      // 不能使用保留字作为变量
?>

可变变量

php
<?php
$var = "name";
$name = "John";

// 可变变量 - 使用$var的值作为变量名
echo $$var; // 输出:John(相当于$name)

// 更复杂的例子
$prefix = "user_";
$user_id = 123;
$user_name = "Alice";
$user_email = "alice@example.com";

$field = "id";
echo ${$prefix . $field}; // 123(相当于$user_id)

$field = "name";
echo ${$prefix . $field}; // Alice(相当于$user_name)

// 动态属性访问
class User {
    public $name = "John";
    public $email = "john@example.com";
}

$user = new User();
$property = "name";
echo $user->$property; // "John"
?>

变量作用域

全局作用域

php
<?php
$globalVar = "我是全局变量";

function testGlobal() {
    // 这不会工作 - $globalVar在这里无法访问
    // echo $globalVar; // 未定义变量错误
    
    // 使用global关键字访问全局变量
    global $globalVar;
    echo $globalVar; // "我是全局变量"
    
    // 修改全局变量
    $globalVar = "全局修改";
}

testGlobal();
echo $globalVar; // "全局修改"

// 替代方法:使用$GLOBALS超全局变量
function testGlobals() {
    echo $GLOBALS['globalVar']; // "全局修改"
    $GLOBALS['globalVar'] = "通过GLOBALS修改";
}

testGlobals();
echo $globalVar; // "通过GLOBALS修改"
?>

局部作用域

php
<?php
function testLocal() {
    $localVar = "我是局部变量";
    echo $localVar; // 工作正常
    
    // 局部变量在函数结束时被销毁
}

testLocal();
// echo $localVar; // 未定义变量错误

// 函数参数是局部的
function greet($name) {
    $message = "你好," . $name;
    return $message;
}

echo greet("Alice"); // "你好,Alice"
// echo $name;    // 未定义变量错误
// echo $message; // 未定义变量错误
?>

静态变量

php
<?php
function counter() {
    static $count = 0; // 只初始化一次
    $count++;
    echo "计数: $count\n";
}

counter(); // 计数: 1
counter(); // 计数: 2
counter(); // 计数: 3

// 类中的静态变量
class PageView {
    public static $totalViews = 0;
    
    public function __construct() {
        self::$totalViews++;
    }
    
    public static function getTotalViews() {
        return self::$totalViews;
    }
}

$page1 = new PageView();
$page2 = new PageView();
echo PageView::getTotalViews(); // 2
?>

超全局变量

$_GET 和 $_POST

php
<?php
// URL: http://example.com/page.php?name=John&age=30
echo $_GET['name']; // "John"
echo $_GET['age'];  // "30"

// 使用空合并运算符安全访问
$name = $_GET['name'] ?? '访客';
$age = $_GET['age'] ?? 0;

// 来自表单的POST数据
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';
    
    // 处理表单数据
    if (!empty($username) && !empty($password)) {
        // 认证用户
    }
}

// 合并GET和POST数据
$allInput = $_REQUEST; // 包含GET和POST(出于安全考虑不推荐)
?>

$_SESSION

php
<?php
// 启动会话
session_start();

// 设置会话变量
$_SESSION['user_id'] = 123;
$_SESSION['username'] = 'john_doe';
$_SESSION['is_logged_in'] = true;

// 访问会话变量
if (isset($_SESSION['is_logged_in']) && $_SESSION['is_logged_in']) {
    echo "欢迎回来," . $_SESSION['username'];
} else {
    echo "请登录";
}

// 删除会话变量
unset($_SESSION['temp_data']);

// 销毁整个会话
// session_destroy();
?>
php
<?php
// 设置cookie
setcookie('user_preference', 'dark_theme', time() + 3600); // 1小时后过期

// 访问cookie
$theme = $_COOKIE['user_preference'] ?? 'light_theme';

// 设置带更多选项的cookie
setcookie('secure_cookie', 'value', [
    'expires' => time() + 3600,
    'path' => '/',
    'domain' => '.example.com',
    'secure' => true,    // 仅HTTPS
    'httponly' => true,  // 无法通过JavaScript访问
    'samesite' => 'Strict'
]);

// 删除cookie
setcookie('user_preference', '', time() - 3600);
?>

$_SERVER

php
<?php
// 服务器和环境信息
echo $_SERVER['HTTP_HOST'];      // example.com
echo $_SERVER['REQUEST_URI'];    // /path/to/page.php?query=value
echo $_SERVER['REQUEST_METHOD']; // GET、POST等
echo $_SERVER['HTTP_USER_AGENT']; // 浏览器信息
echo $_SERVER['REMOTE_ADDR'];    // 客户端IP地址
echo $_SERVER['SERVER_NAME'];    // 服务器主机名
echo $_SERVER['DOCUMENT_ROOT'];  // Web服务器文档根目录

// 有用的服务器变量
$isHTTPS = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';
$currentURL = ($isHTTPS ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$userIP = $_SERVER['REMOTE_ADDR'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'unknown';
?>

$_FILES

php
<?php
// 文件上传处理
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['upload'])) {
    $file = $_FILES['upload'];
    
    // 文件信息
    echo "名称:" . $file['name'];     // 原始文件名
    echo "类型:" . $file['type'];     // MIME类型
    echo "大小:" . $file['size'];     // 文件大小(字节)
    echo "临时:" . $file['tmp_name']; // 临时文件路径
    echo "错误:" . $file['error'];   // 错误代码
    
    // 检查上传错误
    if ($file['error'] === UPLOAD_ERR_OK) {
        $uploadDir = 'uploads/';
        $uploadFile = $uploadDir . basename($file['name']);
        
        if (move_uploaded_file($file['tmp_name'], $uploadFile)) {
            echo "文件上传成功";
        } else {
            echo "上传失败";
        }
    }
}
?>

$_ENV 和 $_GLOBALS

php
<?php
// 环境变量
echo $_ENV['PATH'] ?? '路径未设置';
echo $_ENV['HOME'] ?? '主目录未设置';

// 自定义环境变量(来自.env文件或系统)
$dbHost = $_ENV['DB_HOST'] ?? 'localhost';
$dbName = $_ENV['DB_NAME'] ?? 'myapp';

// $GLOBALS包含所有全局变量
$globalVar = "test";

function showGlobals() {
    // 访问任何全局变量
    echo $GLOBALS['globalVar']; // "test"
    
    // 列出所有全局变量
    foreach ($GLOBALS as $key => $value) {
        if (!is_array($value) && !is_object($value)) {
            echo "$key: $value\n";
        }
    }
}
?>

常量

定义常量

使用 define()

php
<?php
// 基本常量
define('SITE_NAME', '我的网站');
define('VERSION', '1.0.0');
define('MAX_USERS', 1000);
define('PI', 3.14159);
define('DEBUG', true);

// 不区分大小写的常量(PHP 7.3中已废弃)
define('GREETING', '你好', true);
echo greeting; // 可以工作,但不推荐

// 数组常量(PHP 7.0+)
define('FRUITS', ['apple', 'banana', 'orange']);
echo FRUITS[0]; // "apple"

// 带表达式的常量(PHP 5.6+)
define('TIMESTAMP', time());
define('RANDOM_ID', 'ID_' . uniqid());
?>

使用 const 关键字

php
<?php
// 类常量
class MathConstants {
    const PI = 3.14159;
    const E = 2.71828;
    const GOLDEN_RATIO = 1.618;
    
    // 常量表达式(PHP 5.6+)
    const TWO_PI = self::PI * 2;
    
    // 可见性修饰符(PHP 7.1+)
    private const SECRET = 'hidden';
    protected const INTERNAL = 'protected';
    public const PUBLIC = 'visible';
}

// 命名空间常量
namespace MyApp;
const APP_NAME = '我的应用';
const VERSION = '2.0.0';

// 访问常量
echo MathConstants::PI;        // 3.14159
echo MathConstants::TWO_PI;    // 6.28318
echo \MyApp\APP_NAME;          // "我的应用"
?>

魔术常量

php
<?php
// 魔术常量根据上下文变化
echo __LINE__;      // 当前行号
echo __FILE__;      // 当前文件的完整路径
echo __DIR__;       // 当前文件的目录
echo __FUNCTION__;  // 当前函数名
echo __CLASS__;     // 当前类名
echo __TRAIT__;     // 当前Trait名
echo __METHOD__;    // 当前方法名
echo __NAMESPACE__; // 当前命名空间

// 实际例子
function debugInfo() {
    echo "函数:" . __FUNCTION__ . "\n";
    echo "文件:" . __FILE__ . "\n";
    echo "行号:" . __LINE__ . "\n";
}

class Logger {
    public function log($message) {
        $timestamp = date('Y-m-d H:i:s');
        $class = __CLASS__;
        $method = __METHOD__;
        echo "[$timestamp] $class::$method - $message\n";
    }
}

// 包含路径助手
require_once __DIR__ . '/config/database.php';
?>

预定义常量

php
<?php
// PHP版本常量
echo PHP_VERSION;        // PHP版本字符串
echo PHP_MAJOR_VERSION;  // 主版本号
echo PHP_MINOR_VERSION;  // 次版本号

// 系统常量
echo PHP_OS;            // 操作系统
echo PHP_OS_FAMILY;     // 操作系统系列(Windows、Linux等)
echo DIRECTORY_SEPARATOR; // / 或 \ 取决于操作系统
echo PATH_SEPARATOR;    // : 或 ; 取决于操作系统

// 数学常量
echo M_PI;              // 圆周率
echo M_E;               // 欧拉数
echo M_LOG2E;           // E的以2为底的对数

// 文件常量
echo FILE_APPEND;       // file_put_contents()的标志
echo LOCK_EX;           // 排他锁标志

// 错误常量
echo E_ERROR;           // 致命错误
echo E_WARNING;         // 警告
echo E_NOTICE;          // 提示

// 布尔常量
echo TRUE;              // 1
echo FALSE;             // (空)
echo NULL;              // (空)
?>

常量数组和对象

php
<?php
// 数组常量(PHP 7.0+)
const COLORS = ['red', 'green', 'blue'];
const CONFIG = [
    'database' => [
        'host' => 'localhost',
        'name' => 'myapp'
    ],
    'cache' => [
        'driver' => 'redis',
        'ttl' => 3600
    ]
];

echo COLORS[1];                    // "green"
echo CONFIG['database']['host'];   // "localhost"

// 类常量数组
class AppConfig {
    const SUPPORTED_LANGUAGES = ['en', 'es', 'fr', 'de'];
    const DEFAULT_SETTINGS = [
        'theme' => 'light',
        'language' => 'en',
        'timezone' => 'UTC'
    ];
    
    public static function getSetting($key) {
        return self::DEFAULT_SETTINGS[$key] ?? null;
    }
}

echo AppConfig::SUPPORTED_LANGUAGES[0]; // "en"
echo AppConfig::getSetting('theme');    // "light"
?>

变量和常量最佳实践

命名约定

php
<?php
// 变量:驼峰命名或下划线命名
$userName = "john_doe";        // 驼峰命名(推荐)
$user_name = "jane_doe";       // 下划线命名(也可接受)
$isLoggedIn = true;
$has_permission = false;

// 常量:大写字母加下划线
const MAX_LOGIN_ATTEMPTS = 3;
const API_BASE_URL = 'https://api.example.com';
const DEFAULT_TIMEOUT = 30;

// 类常量:大写字母
class UserRole {
    const ADMIN = 'admin';
    const MODERATOR = 'moderator';
    const USER = 'user';
    const GUEST = 'guest';
}

// 私有/受保护变量:下划线前缀(可选)
class MyClass {
    private $_privateVar;
    protected $_protectedVar;
    public $publicVar;
}
?>

变量初始化

php
<?php
// 始终初始化变量
$counter = 0;
$message = '';
$users = [];
$config = null;

// 使用空合并运算符处理可选值
$page = $_GET['page'] ?? 1;
$limit = $_GET['limit'] ?? 10;
$sort = $_GET['sort'] ?? 'name';

// 正确初始化数组
$errors = [];
$data = [
    'users' => [],
    'total' => 0,
    'page' => 1
];

// 使用适当类型的默认值
function processUser($id, $options = []) {
    $defaultOptions = [
        'validate' => true,
        'cache' => false,
        'timeout' => 30
    ];
    
    $options = array_merge($defaultOptions, $options);
    
    // 使用选项处理用户
}
?>

常量组织

php
<?php
// 将相关常量分组
class DatabaseConfig {
    const HOST = 'localhost';
    const PORT = 3306;
    const NAME = 'myapp';
    const CHARSET = 'utf8mb4';
}

class CacheConfig {
    const DRIVER = 'redis';
    const TTL = 3600;
    const PREFIX = 'myapp:';
}

// 使用枚举处理相关常量(PHP 8.1+)
enum Status: string {
    case PENDING = 'pending';
    case APPROVED = 'approved';
    case REJECTED = 'rejected';
}

// 配置类
class Config {
    const ENVIRONMENTS = ['development', 'testing', 'production'];
    
    private static $config = [];
    
    public static function set($key, $value) {
        self::$config[$key] = $value;
    }
    
    public static function get($key, $default = null) {
        return self::$config[$key] ?? $default;
    }
}
?>

安全考虑

php
<?php
// 清理用户输入
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);

// 转义输出
$safeOutput = htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');

// 对数据库查询使用预处理语句
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);

// 不要在常量中暴露敏感信息
// 不好:const DB_PASSWORD = 'secret123';
// 好:使用环境变量
$dbPassword = $_ENV['DB_PASSWORD'] ?? '';

// 验证和清理超全局变量访问
function getQueryParam($key, $default = null, $filter = FILTER_SANITIZE_STRING) {
    return filter_input(INPUT_GET, $key, $filter) ?? $default;
}

$page = getQueryParam('page', 1, FILTER_VALIDATE_INT);
$search = getQueryParam('search', '', FILTER_SANITIZE_STRING);
?>

内存管理

php
<?php
// 在完成后释放大型变量
$largeArray = range(1, 1000000);
// ... 使用数组
unset($largeArray); // 释放内存

// 对大型数据结构使用引用
function processLargeArray(&$array) {
    // 处理数组而不复制
    foreach ($array as &$item) {
        $item = strtoupper($item);
    }
}

// 小心循环引用
class Parent {
    public $children = [];
}

class Child {
    public $parent;
}

$parent = new Parent();
$child = new Child();
$parent->children[] = $child;
$child->parent = $parent;

// 破坏循环引用
unset($child->parent);
unset($parent->children);
?>

高级变量技术

变量函数

php
<?php
// 变量函数
$functionName = 'strlen';
echo $functionName('Hello'); // 5(调用strlen('Hello'))

$mathOp = 'max';
echo $mathOp(1, 5, 3); // 5(调用max(1, 5, 3))

// 动态方法调用
class Calculator {
    public function add($a, $b) {
        return $a + $b;
    }
    
    public function multiply($a, $b) {
        return $a * $b;
    }
}

$calc = new Calculator();
$method = 'add';
echo $calc->$method(5, 3); // 8

// 回调数组
$callback = [$calc, 'multiply'];
echo call_user_func($callback, 4, 5); // 20
?>

Extract 和 Compact

php
<?php
// 从数组提取变量
$data = [
    'name' => 'John',
    'age' => 30,
    'city' => 'New York'
];

extract($data);
echo $name; // "John"
echo $age;  // 30
echo $city; // "New York"

// 将变量压缩到数组
$username = 'alice';
$email = 'alice@example.com';
$active = true;

$user = compact('username', 'email', 'active');
// $user = ['username' => 'alice', 'email' => 'alice@example.com', 'active' => true]

// 带前缀的安全提取
extract($data, EXTR_PREFIX_ALL, 'user');
echo $user_name; // "John"
echo $user_age;  // 30
?>

下一步

现在您已经了解了变量和常量,让我们在运算符中探讨PHP的运算符。

实践练习

  1. 使用常量和静态变量创建一个配置系统
  2. 使用超全局变量构建一个会话管理类
  3. 实现变量验证和清理函数
  4. 练习嵌套函数和类的变量作用域
  5. 创建一个使用魔术常量的调试工具

理解变量和常量对于在PHP应用程序中有效管理数据至关重要!

本站内容仅供学习和研究使用。