变量与常量

变量的基本概念

在编程中,变量就像是存储数据的容器。你可以把变量想象成一个贴了标签的盒子,盒子里可以存放各种类型的数据,并且这些数据在程序运行过程中是可以改变的。

变量的特点:

  • 可变性:变量的值可以在程序执行过程中改变
  • 命名标识:每个变量都有一个唯一的名字来标识它
  • 数据存储:用于存储程序中的各种数据
  • 内存分配:每个变量都会在内存中分配存储空间

PHP变量的命名规则

PHP变量名必须遵循以下规则:

1. 基本规则

  • 变量名必须以美元符号 $ 开头
  • 变量名必须以字母或下划线 _ 开头
  • 变量名只能包含字母、数字和下划线
  • 不能以数字开头
  • 变量名区分大小写
<?php
// ✅ 正确的变量名
$name = "张三";
$age = 25;
$_username = "admin";
$user_name = "张三";
$firstName = "三";
$name1 = "变量名可以包含数字";

// ❌ 错误的变量名
// $2name = "不能以数字开头";
// $user-name = "不能包含连字符";
// $user name = "不能包含空格";
// $@name = "不能包含特殊字符";
?>

2. 命名建议

<?php
// ✅ 推荐的命名方式
$userName = "张三";          // 驼峰命名法 (camelCase)
$user_age = 25;              // 下划线命名法 (snake_case)
$isLoggedIn = true;          // 布尔变量通常以 is 开头
$firstName = "三";           // 描述性的变量名
$usersList = array();        // 数组变量以 List 或 Array 结尾

// ❌ 不推荐的命名方式
$n = "张三";                 // 太短,不够描述性
$a = 25;                     // 含义不明
$aaa = "某个值";             // 无意义的命名
$temp = "临时值";            // 除非真的是临时变量
$USERNAME = "ADMIN";         // 虽然合法,但通常不用全大写(常量除外)
?>

变量的声明和赋值

1. 基本赋值

<?php
// 声明并赋值
$name = "张三";
$age = 25;
$height = 175.5;
$isStudent = true;

// 同时声明多个变量
$a = $b = $c = 0;  // a、b、c 都等于 0

// 链式赋值
$x = 10;
$y = $x;           // y 的值为 10
?>

2. 动态赋值

<?php
// 变量的值可以是其他变量的结果
$firstNumber = 15;
$secondNumber = 10;
$sum = $firstNumber + $secondNumber;  // sum = 25

// 变量的值可以来自函数返回值
$currentTime = date('Y-m-d H:i:s');   // 获取当前时间

// 变量的值可以来自用户输入
$username = $_POST['username'] ?? 'Guest';  // 获取表单提交的用户名
?>

变量的使用

1. 输出变量值

<?php
$name = "李四";
$age = 30;

// 使用 echo 输出
echo $name;        // 输出:李四
echo "我的名字是:" . $name;  // 输出:我的名字是:李四

// 使用双引号字符串插值
echo "我的名字是 {$name},今年 {$age} 岁。";
// 输出:我的名字是李四,今年 30 岁。

// 使用 print 输出
print $name;       // 输出:李四

// 使用 printf 格式化输出
printf("姓名:%s,年龄:%d", $name, $age);
// 输出:姓名:李四,年龄:30
?>

2. 变量在字符串中的使用

<?php
$name = "王五";
$age = 25;

// 双引号中的变量会被解析
echo "你好,{$name}!";     // 输出:你好,王五!
echo "你今年{$age}岁了。";  // 输出:你今年25岁了。

// 单引号中的变量不会被解析
echo '你好,{$name}!';     // 输出:你好,{$name}!
echo '你今年$age岁了。';    // 输出:你今年$age岁了。

// 连接字符串和变量
echo "你好," . $name . "!";  // 输出:你好,王五!
?>

可变变量

PHP支持可变变量,即变量的名字可以动态确定。

<?php
// 普通变量
$var_name = "hello";

// 可变变量:$var_name 的值是 "hello",所以 $$var_name 等于 $hello
$$var_name = "World";

echo $hello;  // 输出:World
echo $var_name;  // 输出:hello

// 更复杂的例子
$user = array("name" => "张三", "age" => 25);
$field = "name";

echo $user[$field];  // 输出:张三

// 多层可变变量
$a = "b";
$b = "c";
$c = "d";
$d = "Hello, World!";

echo $$$$a;  // 等于 $d,输出:Hello, World!
?>

变量的作用域

变量的作用域决定了在代码的哪些地方可以访问这个变量。

1. 局部作用域

<?php
function testFunction() {
    $localVariable = "这是局部变量";  // 只在函数内部可见
    echo $localVariable;  // 正确:在函数内部访问
}

testFunction();  // 输出:这是局部变量
// echo $localVariable;  // 错误:无法在函数外部访问局部变量
?>

2. 全局作用域

<?php
$globalVariable = "这是全局变量";  // 在脚本任何地方都可以访问(除了函数内部)

function testGlobal() {
    // 在函数内部无法直接访问全局变量
    // echo $globalVariable;  // 错误:无法直接访问

    // 使用 global 关键字访问全局变量
    global $globalVariable;
    echo $globalVariable;  // 正确:输出"这是全局变量"

    // 或者使用 $GLOBALS 超全局数组
    echo $GLOBALS['globalVariable'];  // 也正确
}

testGlobal();
?>

3. 静态变量

<?php
function counter() {
    static $count = 0;  // 静态变量,只在第一次调用时初始化
    $count++;
    echo "函数被调用了 {$count} 次<br>";
}

counter();  // 输出:函数被调用了 1 次
counter();  // 输出:函数被调用了 2 次
counter();  // 输出:函数被调用了 3 次
?>

常量

常量是值在程序运行期间不可改变的标识符。通常用于存储不会改变的配置信息。

1. 定义常量

<?php
// 使用 define() 函数定义常量
define("SITE_NAME", "我的网站");
define("MAX_USERS", 1000);
define("PI", 3.14159);

// 使用 const 关键字定义常量(PHP 5.3.0+)
const APP_VERSION = "1.0.0";
const DEBUG_MODE = true;

// 输出常量的值
echo SITE_NAME;        // 输出:我的网站
echo MAX_USERS;        // 输出:1000
echo APP_VERSION;      // 输出:1.0.0
?>

2. 常量的命名规则

<?php
// ✅ 推荐的常量命名方式
define("SITE_NAME", "我的网站");
define("MAX_FILE_SIZE", 5242880);
define("API_KEY", "your_api_key_here");

// ❌ 不推荐的命名方式
define("siteName", "我的网站");  // 不使用大写和下划线
define("MAX_SIZE", 5242880);    // 不够描述性
?>

3. 常量的特点

  • 不可改变:一旦定义,常量的值不能修改
  • 大小写敏感(默认):NAMEname 是不同的常量
  • 全局作用域:常量在整个脚本中都可以访问
  • 前面不加美元符号:访问常量时不需要 $
<?php
// 定义常量
define("SITE_NAME", "我的网站");

// 正确的访问方式
echo SITE_NAME;  // 输出:我的网站

// ❌ 错误的访问方式
// echo $SITE_NAME;  // 错误:常量前不需要美元符号

// ❌ 尝试修改常量
// define("SITE_NAME", "新名称");  // 错误:常量不能重新定义
?>

4. 大小写不敏感的常量

<?php
// 第三个参数为 true 时,常量大小写不敏感
define("GREETING", "Hello World", true);

echo GREETING;   // 输出:Hello World
echo greeting;   // 输出:Hello World
echo Greeting;   // 输出:Hello World

// 但推荐总是使用大写命名,保持代码一致性
?>

5. 魔术常量

PHP提供了一些特殊的预定义常量,称为"魔术常量":

<?php
echo __LINE__;    // 当前行号
echo __FILE__;    // 文件的完整路径和文件名
echo __DIR__;     // 文件所在的目录
echo __FUNCTION__;  // 当前函数名
echo __CLASS__;   // 当前类名
echo __METHOD__;  // 当前方法名
echo __NAMESPACE__;  // 当前命名空间

// 示例
function myFunction() {
    echo "函数名:" . __FUNCTION__ . "<br>";
    echo "文件名:" . __FILE__ . "<br>";
    echo "行号:" . __LINE__ . "<br>";
}

myFunction();
?>

变量的类型判断和转换

1. 类型判断函数

<?php
$var = "Hello World";

// 检查变量类型
if (is_string($var)) {
    echo "这是一个字符串<br>";
}

if (is_int(42)) {
    echo "这是一个整数<br>";
}

if (is_array($arrayVar)) {
    echo "这是一个数组<br>";
}

// 检查变量是否已定义
if (isset($undefinedVar)) {
    echo "变量已定义<br>";
} else {
    echo "变量未定义<br>";
}

// 检查变量是否为空
if (empty($emptyVar)) {
    echo "变量为空<br>";
}

// 检查变量是否存在且不为空
if (isset($var) && !empty($var)) {
    echo "变量存在且不为空<br>";
}
?>

2. 类型转换

<?php
// 隐式类型转换
$string = "123";
$number = $string + 1;  // 自动将字符串转换为整数
echo $number;           // 输出:124

// 显式类型转换
$string = "45.67";
$integer = (int)$string;     // 转换为整数:45
$float = (float)$string;     // 转换为浮点数:45.67
$boolean = (bool)$string;    // 转换为布尔值:true

// 使用类型转换函数
$int_value = intval("123abc");   // 转换为整数:123
$float_value = floatval("12.34abc");  // 转换为浮点数:12.34
$bool_value = boolval("hello");   // 转换为布尔值:true

// 获取变量类型
$var = 123;
echo gettype($var);  // 输出:integer

// 设置变量类型
settype($var, "string");  // 将变量转换为字符串类型
?>

实际应用示例

示例1:用户信息管理系统

<?php
// ========================================
// 用户信息管理系统
// 功能:展示用户注册、信息处理的基本流程
// ========================================

// 系统配置常量
define("MIN_AGE", 18);              // 最小年龄限制
define("MAX_AGE", 120);             // 最大年龄限制
define("MIN_USERNAME_LENGTH", 3);   // 用户名最小长度
define("MAX_USERNAME_LENGTH", 20);  // 用户名最大长度

// 用户注册函数
function registerUser($username, $email, $age) {
    // 输入验证
    if (strlen($username) < MIN_USERNAME_LENGTH) {
        return "用户名太短,至少需要" . MIN_USERNAME_LENGTH . "个字符";
    }

    if ($age < MIN_AGE || $age > MAX_AGE) {
        return "年龄必须在" . MIN_AGE . "到" . MAX_AGE . "之间";
    }

    // 处理用户数据
    $userData = array(
        'username' => $username,
        'email' => $email,
        'age' => $age,
        'registration_date' => date('Y-m-d H:i:s')
    );

    // 在实际应用中,这里会将数据保存到数据库
    // 这里只是模拟保存过程
    echo "用户注册成功!<br>";
    echo "用户名:{$userData['username']}<br>";
    echo "邮箱:{$userData['email']}<br>";
    echo "年龄:{$userData['age']}<br>";
    echo "注册时间:{$userData['registration_date']}<br>";

    return true;
}

// 用户信息显示函数
function displayUserInfo($userData) {
    // 定义状态常量
    define("STATUS_ACTIVE", "活跃");
    define("STATUS_INACTIVE", "未激活");
    define("STATUS_BANNED", "已禁用");

    // 根据用户状态显示不同信息
    $status = $userData['status'] ?? STATUS_INACTIVE;

    echo "<div class='user-info'>";
    echo "<h3>用户信息</h3>";
    echo "<p>用户名:{$userData['username']}</p>";
    echo "<p>邮箱:{$userData['email']}</p>";
    echo "<p>年龄:{$userData['age']}</p>";
    echo "<p>状态:{$status}</p>";

    // 根据年龄显示不同的欢迎信息
    if ($userData['age'] < 25) {
        echo "<p class='young'>年轻人,欢迎加入我们的平台!</p>";
    } elseif ($userData['age'] < 50) {
        echo "<p class='middle'>很高兴认识您!</p>";
    } else {
        echo "<p class='senior'>欢迎前辈加入我们的社区!</p>";
    }

    echo "</div>";
}

// 模拟用户注册
$username = "张小明";
$email = "xiaoming@example.com";
$age = 25;

$result = registerUser($username, $email, $age);

if ($result === true) {
    // 创建用户数据数组
    $newUser = array(
        'username' => $username,
        'email' => $email,
        'age' => $age,
        'status' => STATUS_ACTIVE  // 使用常量
    );

    // 显示用户信息
    displayUserInfo($newUser);
} else {
    echo "注册失败:" . $result;
}
?>

示例2:简单的配置管理系统

<?php
// ========================================
// 网站配置管理系统
// ========================================

// 环境配置常量
define("ENV_DEVELOPMENT", "development");
define("ENV_PRODUCTION", "production");
define("ENV_TESTING", "testing");

// 当前环境(在实际应用中,这个值可能来自环境变量)
$currentEnvironment = ENV_DEVELOPMENT;

// 根据环境加载不同的配置
switch ($currentEnvironment) {
    case ENV_DEVELOPMENT:
        // 开发环境配置
        define("DEBUG_MODE", true);
        define("ERROR_REPORTING", E_ALL);
        define("DB_HOST", "localhost");
        define("DB_NAME", "myapp_dev");
        define("LOG_LEVEL", "debug");
        break;

    case ENV_PRODUCTION:
        // 生产环境配置
        define("DEBUG_MODE", false);
        define("ERROR_REPORTING", 0);
        define("DB_HOST", "prod.db.example.com");
        define("DB_NAME", "myapp_prod");
        define("LOG_LEVEL", "error");
        break;

    case ENV_TESTING:
        // 测试环境配置
        define("DEBUG_MODE", true);
        define("ERROR_REPORTING", E_ALL & ~E_DEPRECATED);
        define("DB_HOST", "test.db.example.com");
        define("DB_NAME", "myapp_test");
        define("LOG_LEVEL", "warning");
        break;

    default:
        die("未知的环境配置");
}

// 网站基础配置常量
define("SITE_NAME", "我的PHP网站");
define("SITE_VERSION", "1.0.0");
define("AUTHOR", "张三");
define("CONTACT_EMAIL", "admin@example.com");

// 文件上传配置
define("MAX_UPLOAD_SIZE", 5 * 1024 * 1024);  // 5MB
define("ALLOWED_FILE_TYPES", array('jpg', 'png', 'gif', 'pdf'));
define("UPLOAD_PATH", "/var/www/uploads/");

// 会话配置
define("SESSION_LIFETIME", 3600);  // 1小时
define("COOKIE_PATH", "/");
define("COOKIE_DOMAIN", "example.com");

// 配置显示函数
function displayConfiguration() {
    echo "<h2>网站配置信息</h2>";
    echo "<table border='1'>";
    echo "<tr><th>配置项</th><th>值</th><th>说明</th></tr>";

    // 显示基本配置
    echo "<tr><td>网站名称</td><td>" . SITE_NAME . "</td><td>网站标题</td></tr>";
    echo "<tr><td>网站版本</td><td>" . SITE_VERSION . "</td><td>当前版本号</td></tr>";
    echo "<tr><td>调试模式</td><td>" . (DEBUG_MODE ? "开启" : "关闭") . "</td><td>是否显示调试信息</td></tr>";
    echo "<tr><td>错误报告</td><td>" . ERROR_REPORTING . "</td><td>错误报告级别</td></tr>";

    // 显示文件配置
    echo "<tr><td>最大上传大小</td><td>" . (MAX_UPLOAD_SIZE / 1024 / 1024) . " MB</td><td>文件上传限制</td></tr>";

    // 显示会话配置
    echo "<tr><td>会话有效期</td><td>" . SESSION_LIFETIME . " 秒</td><td>用户登录保持时间</td></tr>";

    echo "</table>";
}

// 环境检查函数
function checkEnvironment() {
    echo "<h2>环境检查</h2>";

    // PHP版本检查
    $phpVersion = PHP_VERSION;
    echo "<p>PHP版本:{$phpVersion}</p>";

    // 必要的PHP扩展检查
    $requiredExtensions = array('mysqli', 'gd', 'curl');
    echo "<p>必要的PHP扩展:</p>";
    echo "<ul>";

    foreach ($requiredExtensions as $extension) {
        if (extension_loaded($extension)) {
            echo "<li style='color: green;'>✓ {$extension} - 已安装</li>";
        } else {
            echo "<li style='color: red;'>✗ {$extension} - 未安装</li>";
        }
    }
    echo "</ul>";

    // 目录权限检查
    $uploadPath = UPLOAD_PATH;
    if (is_writable($uploadPath)) {
        echo "<p style='color: green;'>✓ 上传目录可写</p>";
    } else {
        echo "<p style='color: red;'>✗ 上传目录不可写,请检查权限</p>";
    }
}

// 显示配置信息
displayConfiguration();
checkEnvironment();
?>

常见错误和解决方案

1. 变量未定义错误

<?php
// ❌ 错误示例
echo $undefinedVariable;  // 会产生 Notice: Undefined variable

// ✅ 正确的做法
$variable = "默认值";
echo $variable;

// 或者使用 isset() 检查
if (isset($variable)) {
    echo $variable;
} else {
    echo "变量未定义";
}

// 使用 null 合并运算符(PHP 7.0+)
echo $variable ?? "默认值";
?>

2. 变量名拼写错误

<?php
$userName = "张三";

// ❌ 常见错误
// echo $username;  // 变量名大小写不一致
// echo $user_name; // 命名风格不一致

// ✅ 正确的访问
echo $userName;

// 使用一致的命名风格
$user_name = "李四";  // 下划线命名法
$userAge = 25;        // 驼峰命名法
?>

3. 常量使用错误

<?php
define("SITE_NAME", "我的网站");

// ❌ 常见错误
// echo $SITE_NAME;    // 错误:常量前不需要美元符号
// define("SITE_NAME", "新名称");  // 错误:常量不能重新定义

// ✅ 正确的使用
echo SITE_NAME;

// 使用 defined() 检查常量是否已定义
if (defined("SITE_NAME")) {
    echo "常量 SITE_NAME 已定义";
}

// 使用 constant() 函数动态访问常量
$constantName = "SITE_NAME";
echo constant($constantName);  // 等同于 echo SITE_NAME;
?>

4. 变量作用域错误

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

function testScope() {
    $localVar = "局部变量";

    // ❌ 错误:不能直接访问全局变量
    // echo $globalVar;

    // ✅ 正确:使用 global 关键字
    global $globalVar;
    echo $globalVar;

    // ✅ 正确:使用 $GLOBALS 数组
    echo $GLOBALS['globalVar'];
}

testScope();

// ❌ 错误:不能在函数外部访问局部变量
// echo $localVar;
?>

练习题

基础练习

  1. 变量命名练习 以下哪些是正确的变量名?哪些是错误的?

    $name, $1name, $name1, $_name, $name-1, $Name, $user_name, $userName
    
  2. 常量定义练习 定义以下常量并输出它们的值:

    • 网站名称:"我的PHP学习网站"
    • 最大用户数:1000
    • 版本号:"1.0.0"
  3. 变量赋值练习 创建变量存储你的个人信息(姓名、年龄、邮箱、是否为学生),并格式化输出。

进阶练习

  1. 变量作用域练习 解释以下代码的输出结果:

    <?php
    $a = 10;
    
    function test() {
        $a = 20;
        echo $a;
    }
    
    test();
    echo $a;
    ?>
    
  2. 可变变量练习 使用可变变量实现动态访问:

    <?php
    $user = array('name' => '张三', 'age' => 25);
    $field = 'name';
    
    // 使用可变变量输出用户名和年龄
    ?>
    
  3. 配置管理系统 创建一个简单的配置文件,使用常量定义数据库连接信息、网站基本设置等。

实践练习

  1. 用户注册表单处理 创建一个处理用户注册的脚本,包括:

    • 表单数据接收
    • 输入验证(使用常量定义验证规则)
    • 错误处理
    • 成功消息显示
  2. 多语言支持系统 使用常量实现简单的多语言支持:

    <?php
    // 定义语言常量
    define("LANG_EN", "en");
    define("LANG_CN", "zh");
    
    // 根据语言设置显示不同的内容
    ?>
    

总结

变量和常量是PHP编程的基础,理解它们的特性对于编写高质量的代码至关重要:

变量的关键点:

  • $ 开头,命名要有描述性
  • 区分大小写,保持命名风格一致
  • 理解作用域:局部、全局、静态
  • 使用可变变量实现动态访问

常量的关键点:

  • 值不可改变,适合存储配置信息
  • 全局访问,不使用 $ 符号
  • 推荐大写命名,使用下划线分隔
  • 善用魔术常量获取代码位置信息

最佳实践:

  • 有意义的命名:让代码自文档化
  • 适当的注释:解释复杂的业务逻辑
  • 类型检查:使用 isset()empty() 防止错误
  • 作用域控制:合理使用全局变量和局部变量
  • 常量优先:对于不变的值优先使用常量

掌握变量和常量的使用是PHP编程的第一步,接下来我们将学习PHP中的数据类型,了解PHP能够处理的各种数据。

下一步学习:掌握变量和常量后,让我们继续学习PHP中的数据类型。