变量基础
变量是程序中用于存储数据的"容器"。PHP 中的变量以美元符号 $ 开头,具有弱类型特性,可以存储不同类型的数据。理解变量的基本概念是 PHP 编程的核心基础。
基础概念
PHP 中的变量用一个美元符号 $ 后面跟变量名来表示。变量名区分大小写。PHP 是一种弱类型(动态类型)语言,变量不需要预先声明类型,赋值时自动确定类型。
变量的基本特征
- 以
$符号开头 - 变量名区分大小写(
$name和$Name是不同变量) - 无需预先声明,赋值即创建
- 可以在不同时候存储不同类型的值
变量命名规则
有效的变量名
变量名由字母(A-Z、a-z,以及字节值 128~255 的字符)或下划线 _ 开头,后面可以跟任意数量的字母、数字或下划线。正则表达式为:^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$。
<?php
declare(strict_types=1);
// 有效的变量名
$name = "Alice";
$firstName = "Bob";
$_4site = "example.com"; // 以下划线开头
$i站点 = "mansikka"; // 包含多字节字符(UTF-8 编码有效)
echo $name . "\n"; // 输出: Alice
echo $firstName . "\n"; // 输出: Bob
// 变量名区分大小写
$var = "Bob";
$Var = "Joe";
echo "$var, $Var\n"; // 输出: Bob, Joe无效的变量名
<?php
declare(strict_types=1);
// 错误:以数字开头
// $4site = "not yet"; // Parse error
// 错误:以特殊字符开头
// $@var = "test"; // Parse error动态访问非标准变量名
PHP 接受任意字节序列作为变量名,不遵循上述命名规则的变量名可以通过花括号语法动态访问:
<?php
declare(strict_types=1);
// 使用花括号访问非标准变量名
${'invalid-name'} = "bar";
$name = "invalid-name";
echo ${'invalid-name'} . "\n"; // 输出: bar
echo $$name . "\n"; // 输出: bar(可变变量)$this 是特殊变量
$this 是一个特殊变量,在对象方法中引用当前对象实例。PHP 7.1.0 之后,$this 不能被赋值(之前可以通过可变变量间接赋值)。
赋值方式
传值赋值(默认)
PHP 变量默认使用传值赋值。将一个变量的值赋给另一个变量时,会复制原始值。改变其中一个变量不会影响另一个:
<?php
declare(strict_types=1);
// 传值赋值
$a = "Hello";
$b = $a; // $b 获得了 $a 的副本
$b = "World"; // 修改 $b 不影响 $a
echo $a . "\n"; // 输出: Hello
echo $b . "\n"; // 输出: World对于对象类型,虽然变量本身是传值赋值(复制了对象的引用指针),但两者指向同一个对象实例。修改对象的属性会影响两个变量:
<?php
declare(strict_types=1);
class Config
{
public string $name = "default";
}
$obj1 = new Config();
$obj2 = $obj1; // 传值赋值,但都指向同一对象
$obj2->name = "custom";
echo $obj1->name . "\n"; // 输出: custom(受影响)
echo $obj2->name . "\n"; // 输出: custom引用赋值
引用赋值使用 & 符号,使新变量成为原变量的别名。两者共享同一个值,修改其中一个会影响另一个:
<?php
declare(strict_types=1);
// 引用赋值
$foo = "Bob";
$bar = &$foo; // $bar 是 $foo 的引用
$bar = "My name is {$bar}";
echo $bar . "\n"; // 输出: My name is Bob
echo $foo . "\n"; // 输出: My name is Bob(同样被修改)引用赋值的限制
只有具名变量才能被引用赋值,不能对没有名字的表达式使用引用:
<?php
declare(strict_types=1);
$foo = 25;
$bar = &$foo; // 合法:引用已命名变量
// $bar = &(24 * 7); // 非法:不能引用无名字的表达式
function test(): int
{
return 25;
}
// $bar = &test(); // 非法:函数没有通过引用返回详细说明
类型推导
PHP 是弱类型语言,变量的类型由赋值的内容自动决定。可以使用 gettype() 函数查看变量类型:
<?php
declare(strict_types=1);
// PHP 自动推导变量类型
$intVar = 42; // int
$floatVar = 3.14; // float
$stringVar = "Hello"; // string
$boolVar = true; // bool
$arrayVar = [1, 2, 3]; // array
$nullVar = null; // null
echo gettype($intVar) . "\n"; // integer
echo gettype($floatVar) . "\n"; // double
echo gettype($stringVar) . "\n"; // string
echo gettype($boolVar) . "\n"; // boolean
echo gettype($arrayVar) . "\n"; // array
echo gettype($nullVar) . "\n"; // NULL未初始化的变量
PHP 不强制声明变量,访问未初始化的变量会触发 E_WARNING(PHP 8.0.0 之前是 E_NOTICE),其默认值为 null。可以使用 isset() 检测变量是否已初始化:
<?php
declare(strict_types=1);
// 未初始化变量
// var_dump($undefinedVar); // Warning: Undefined variable
// 使用 isset() 安全检测
if (isset($undefinedVar)) {
echo "Variable is set\n";
} else {
echo "Variable is not set\n"; // 输出此行
}
// 使用 null 合并运算符(PHP 7.0+)提供默认值
$name = $undefinedVar ?? "default";
echo $name . "\n"; // 输出: default自动数组生成
将元素追加到未定义的变量时,PHP 会自动创建一个数组:
<?php
declare(strict_types=1);
// 自动创建数组
$unsetArray[] = "value"; // 不会产生警告
$unsetArray[] = "another";
print_r($unsetArray);
// 输出: Array ( [0] => value [1] => another )警告
依赖未初始化变量的默认行为是有风险的,尤其是在使用 include 包含文件时。始终显式初始化变量。
销毁变量
使用 unset() 语言结构可以销毁变量:
<?php
declare(strict_types=1);
$name = "Alice";
echo isset($name) ? "set" : "not set"; // 输出: set
unset($name);
echo isset($name) ? "set" : "not set"; // 输出: not set
// 销毁引用
$a = "value";
$b = &$a;
unset($b); // 只解除 $b 的引用,不影响 $a
echo $a . "\n"; // 输出: value实战示例
类型检测函数
<?php
declare(strict_types=1);
function analyzeVariable(mixed $value): string
{
$type = gettype($value);
$result = "Type: {$type}";
if (is_int($value)) {
$result .= " | Integer: {$value}";
} elseif (is_float($value)) {
$result .= " | Float: {$value}";
} elseif (is_string($value)) {
$result .= " | String length: " . strlen($value);
} elseif (is_bool($value)) {
$result .= " | Boolean: " . ($value ? "true" : "false");
} elseif (is_null($value)) {
$result .= " | Null value";
} elseif (is_array($value)) {
$result .= " | Array count: " . count($value);
}
return $result;
}
echo analyzeVariable(42) . "\n";
echo analyzeVariable(3.14) . "\n";
echo analyzeVariable("Hello World") . "\n";
echo analyzeVariable(true) . "\n";
echo analyzeVariable([1, 2, 3]) . "\n";安全的变量初始化模式
<?php
declare(strict_types=1);
/**
* 安全地获取配置值
*
* 使用嵌套的 null 合并运算符(PHP 7.0+)安全访问深层配置
*/
function getConfig(string $key, mixed $default = null): mixed
{
static $config = null;
if ($config === null) {
$config = [
"database" => [
"host" => "localhost",
"port" => 3306,
"name" => "myapp",
],
"cache" => [
"enabled" => true,
"ttl" => 3600,
],
];
}
// 安全的多层访问
return match ($key) {
"db.host" => $config["database"]["host"] ?? $default,
"db.port" => $config["database"]["port"] ?? $default,
"db.name" => $config["database"]["name"] ?? $default,
"cache.enabled" => $config["cache"]["enabled"] ?? $default,
"cache.ttl" => $config["cache"]["ttl"] ?? $default,
default => $default,
};
}
echo getConfig("db.host") . "\n"; // localhost
echo getConfig("db.port") . "\n"; // 3306
echo getConfig("unknown", "N/A") . "\n"; // N/A引用与传值的实际应用
<?php
declare(strict_types=1);
// 引用在修改函数参数时的用途
function addPrefix(string &$str, string $prefix): void
{
$str = $prefix . $str;
}
$title = "World";
addPrefix($title, "Hello, ");
echo $title . "\n"; // 输出: Hello, World
// 多个变量交换(通过引用)
$a = "first";
$b = "second";
function swap(string &$x, string &$y): void
{
$temp = $x;
$x = $y;
$y = $temp;
}
swap($a, $b);
echo "a={$a}, b={$b}\n"; // a=second, b=first注意事项
1. 变量与常量的区别
常量和变量在不同的命名空间中。true 和 $TRUE 是完全不同的:
<?php
declare(strict_types=1);
define("MY_CONST", 100);
$myConst = 200;
echo MY_CONST . "\n"; // 100(常量)
echo $myConst . "\n"; // 200(变量)2. 不要依赖未初始化变量
<?php
declare(strict_types=1);
// 危险:依赖未初始化变量
function unsafeIncrement(): int
{
// $count 未初始化,PHP 8 会产生 E_WARNING
// return ++$count;
// 安全的做法:
static $count = 0;
return ++$count;
}3. 避免变量名与超级全局变量冲突
虽然不禁止,但避免创建与 $_GET、$_POST、$_SERVER 等同名的变量:
<?php
declare(strict_types=1);
// 不推荐:可能与内置变量混淆
// $_GET = "custom";
// 推荐:使用有意义的、不会冲突的名称
$getParams = $_GET;最佳实践
- 始终初始化变量:在使用前显式赋初值,避免依赖默认行为
- 使用有意义的变量名:
$userAge比$a更好理解 - 遵循驼峰命名:按照 PSR-12,变量使用
$camelCase风格 - 使用
isset()或??:安全访问可能未定义的变量 - 谨慎使用引用:引用会降低代码可读性,仅在必要时使用
- 使用
declare(strict_types=1):在严格模式下编写更安全的代码 - 利用类型声明:PHP 7.0+ 支持函数参数和返回值类型声明
下一节
理解了变量的基本概念后,接下来将深入学习变量的作用域规则——全局变量、局部变量、静态变量以及超级全局变量。请阅读 变量作用域。