PHP 变量与数据类型
AI 辅助生成本文由 AI 起草并经人工核查,示例均标明软件版本;发现错误请以官方文档为准。
PHP 是弱类型语言,变量不需要声明类型,但这不代表类型不重要——大多数 PHP 的诡异行为都来自隐式类型转换。这一篇先立好基础。
环境准备
确认 PHP 版本(本篇基于 PHP 8.4,示例在 8.x 均可运行):
php -v
# PHP 8.4.x (cli)
把示例保存为 demo.php,用 php demo.php 运行。想跑 Web 示例时用内置服务器:
php -S localhost:8000
浏览器访问 http://localhost:8000/demo.php 即可,不需要额外装 Nginx 或 Apache。
变量:$ 开头
<?php
$name = "ann";
$age = 30;
$price = 9.9;
变量名以 $ 开头,区分大小写($name 与 $Name 是两个变量)。命名用小写字母加下划线,不用驼峰(PSR 规范与 PHP 自身风格如此)。
不需要声明,直接赋值即可使用;但使用未定义的变量会得到 null 并产生警告:
echo $city; // Warning: Undefined variable $city,输出空字符串
先赋值再使用,用 isset() 判断变量是否已定义且有值。
四种标量类型
$int = 42; // int
$float = 3.14; // float
$string = "hello"; // string
$bool = true; // bool
另外还有两个“特殊”类型:
$nothing = null; // null,表示没有值
以及复合类型 array 与 object(见本篇后面与本系列第 2 篇)。
用 var_dump() 查看类型与值,调试时比 echo 有用得多:
var_dump(42); // int(42)
var_dump("42"); // string(2) "42"
var_dump(3.0); // float(3)
var_dump(true); // bool(true)
var_dump(null); // NULL
类型判断函数:
is_int(42); // true
is_string("42"); // true
is_float(3.14); // true
is_bool(true); // true
is_null(null); // true
is_array([1]); // true
is_numeric("42"); // true,字符串内容是数字
字符串:单引号与双引号
$name = "ann";
echo 'hello $name'; // hello $name(单引号不解析变量)
echo "hello $name"; // hello ann(双引号解析变量)
echo "hello {$name}!"; // hello ann!(用花括号界定变量名)
拼接用 .(不是 +):
echo "hello " . $name; // hello ann
$total = "共 " . 3 . " 件";
用 + 拼接字符串会得到 0,这是初学者最常见的错误:"a" + "b" 结果是 0 并产生警告。
数组:PHP 的主力容器
PHP 的数组同时承担了「列表」和「字典」两种角色:
$list = [1, 2, 3]; // 索引数组
$user = ["name" => "ann", "age" => 30]; // 关联数组
$mixed = [1, "name" => "ann"]; // 允许混用,但不推荐
读写:
echo $list[0]; // 1
echo $user["name"]; // ann
$user["city"] = "Shenzhen"; // 新增
unset($user["age"]); // 删除
访问不存在的键会得到 null 并产生警告,取值前先判断:
echo $user["nickname"] ?? "匿名"; // 空值合并,安全
详细用法见本系列第 2 篇。
松散比较:== 与 ===
PHP 有两种相等:
"42" == 42 // true (先转类型再比较)
"42" === 42 // false (类型也必须相同)
PHP 8 改进了数字与字符串的松散比较,但 == 依然容易出意外:
0 == "abc" // PHP 8 起为 false(PHP 7 是 true,历史坑)
"" == null // true
false == "" // true
[] == false // true
结论:一律用 ===,需要区分 0 与 "" 时尤其如此。
自动类型转换
"10" + 5 // 15,字符串转成数字
"10abc" + 5 // 15 并产生 Warning(非数字字符串)
10 / "a" // 抛出 DivisionByZeroError 或 TypeError,取决于版本
"3.5" * 2 // 7.0
需要转换时写明确:
$count = (int) "42"; // 42,强制转换
$text = (string) 42; // "42"
$flag = (bool) ""; // false
falsy 值
需要布尔判断时,以下值为 false,其余为 true:
false, 0, 0.0, "", "0", [], null
注意 "0" 在 PHP 里是 falsy(与其他语言不同):
if ("0") {
echo "执行";
} else {
echo "跳过"; // 实际走这里
}
判断「字符串非空」用 strlen($s) > 0 或 $s !== "",不要用 if ($s)。
declare(strict_types=1)
PHP 默认会在函数调用时自动转换参数类型:
function add(int $a, int $b): int {
return $a + $b;
}
add("3", "4"); // 7,字符串被自动转成 int
在文件顶部声明严格类型后,传错类型直接抛 TypeError:
<?php
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
add("3", "4"); // TypeError
新项目建议所有文件都加 declare(strict_types=1);,把类型问题从“静默转换”变成“明确报错”。注意它只影响当前文件内的函数调用,不影响返回值的外部处理。
变量作用域
$global = "外层";
function show() {
echo $global; // Warning: Undefined variable $global
}
函数内部不会自动访问全局变量。需要使用时显式声明:
function show(): void {
global $global;
echo $global; // "外层"
}
但过度使用 global 会让代码难以追踪,更好的做法是把值作为参数传入。
常见错误与注意事项
- 用
+拼接字符串:结果是0,字符串拼接必须用.。 - 单引号里写
$name期望被解析:单引号原样输出,改用双引号或拼接。 - 用
==比较:"0"、""、null之间的意外相等,改用===。 - 函数内直接用全局变量:拿不到值,用参数传递而不是
global。 - 忘记
declare(strict_types=1):参数被静默转换,类型错误延后爆发。 - 访问不存在的数组键:
null+ 警告,用??兜底。
小结
- 变量以
$开头,使用前先赋值,用isset()判断。 - 字符串拼接用
.;双引号解析变量,单引号不解析。 - 比较一律用
===;"0"在 PHP 里是 falsy。 - 新文件都写
declare(strict_types=1);。 - 函数不会自动拿到全局变量,用参数传递。