PHP 变量与数据类型

第 1 章 · 共 16 章

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 会让代码难以追踪,更好的做法是把值作为参数传入。

常见错误与注意事项

  1. 用 + 拼接字符串:结果是 0,字符串拼接必须用 .。
  2. 单引号里写 $name 期望被解析:单引号原样输出,改用双引号或拼接。
  3. 用 == 比较:"0"、""、null 之间的意外相等,改用 ===。
  4. 函数内直接用全局变量:拿不到值,用参数传递而不是 global。
  5. 忘记 declare(strict_types=1):参数被静默转换,类型错误延后爆发。
  6. 访问不存在的数组键:null + 警告,用 ?? 兜底。

小结

  • 变量以 $ 开头,使用前先赋值,用 isset() 判断。
  • 字符串拼接用 .;双引号解析变量,单引号不解析。
  • 比较一律用 ===;"0" 在 PHP 里是 falsy。
  • 新文件都写 declare(strict_types=1);。
  • 函数不会自动拿到全局变量,用参数传递。

下一步