主题
内置函数
PHP 自带大量函数,打开就能用,不必自己写:数个数、判断空、转义 HTML、调试打印。前面已经用过 var_dump()、count()、htmlspecialchars()。本篇先弄清「怎么调用」,再把最容易混的三个讲透:isset、is_null、empty。
php
<?php
$name = "PHP";
var_dump(isset($name));
var_dump(is_null($name));
var_dump(empty($name));手册入口:https://www.php.net/manual/zh/funcref.php。不确定某个函数时,搜函数名即可。
怎么调用
函数有名字、参数、返回值。括号不能省(语言结构另说):
php
<?php
$langs = ["PHP", "HTML", "SQL"];
$n = count($langs); // 传入数组,返回 int 3
echo strlen("PHP"), "\n"; // 3,按字节计长度
var_dump(in_array("PHP", $langs, true));参数个数、类型以手册为准。多出来的参数 PHP 8 会 ArgumentCountError;该传却没传同样报错。
返回值要接住才会留下来:
php
<?php
$s = "abc";
strtoupper($s); // 返回 "ABC",但没赋给变量,$s 仍是 abc
$s = strtoupper($s); // 现在 $s 是 ABC多数内置函数不改你传入的变量(sort() 这类排序函数除外,会改原数组)。
语言结构还是函数
有几样写起来像函数,其实是语言结构,手册里会标明:
| 写法 | 类型 | 说明 |
|---|---|---|
isset / empty / unset | 语言结构 | 可以探测未定义变量且不 Warning |
echo / print | 语言结构 | 见 echo 与 print |
is_null() | 函数 | 未定义变量会 Warning |
count() / strlen() | 函数 | 普通调用 |
语言结构不能当回调、不能写成 $fn = "isset"; $fn($x)。is_null 可以,但没必要。
日常仍写成 isset($x)、empty($x),和函数同一套括号习惯即可。
isset:有没有、且不是 null
isset($x) 为 true 当且仅当:这个名字已经定义,并且当前值不是 null。
php
<?php
$name = "小明";
$blank = "";
$zero = 0;
$none = null;
var_dump(isset($name)); // true
var_dump(isset($blank)); // true,空字符串也算「有」
var_dump(isset($zero)); // true,0 也算「有」
var_dump(isset($none)); // false,值是 null
var_dump(isset($missing)); // false,未定义,且不报警可以一次检查多个,全部 isset 才为 true(从左短路,左边失败右边不再看):
php
<?php
$a = 1;
$b = 2;
var_dump(isset($a, $b)); // true
var_dump(isset($a, $missing)); // false数组键同样适用,见 数组:
php
<?php
$user = ["name" => "小明", "bio" => null];
var_dump(isset($user["name"])); // true
var_dump(isset($user["bio"])); // false,键在但值是 null
var_dump(isset($user["age"])); // false,没有这个键「键在不在、哪怕值是 null」要用 array_key_exists(),不要用 isset。
unset($x) 之后 isset($x) 为 false,效果接近「从未定义」。
is_null:是不是 null
is_null($x) 等价于 $x === null。它是真正的函数,要求这个变量已经存在:
php
<?php
$none = null;
$zero = 0;
$name = "小明";
var_dump(is_null($none)); // true
var_dump(is_null($zero)); // false
var_dump(is_null($name)); // false
var_dump($none === null); // true,更常见的写法未定义时 PHP 8 会 Warning,再把变量当成 null,于是 is_null 还返回 true:
php
<?php
var_dump(is_null($missing));
// Warning: Undefined variable $missing
// bool(true)所以:
- 变量肯定已经赋值(包括可能被赋成
null)→ 用=== null或is_null - 变量可能根本没定义 → 不要
is_null,用isset或??
函数名叫 is_null(中间有下划线),没有 isnull()。
empty:当成布尔假就算空
empty($x) 为 true 当「拿它当布尔值是假」,或者它未定义。未定义时不 Warning。
下面这些 empty 都是 true:
| 值 | 说明 |
|---|---|
| 未定义变量 | 不报警 |
null | |
false | |
0、0.0 | 整数 / 浮点零 |
"" | 空字符串 |
"0" | 字符串零,最容易踩坑 |
[] | 空数组 |
php
<?php
var_dump(empty(0)); // true
var_dump(empty("0")); // true
var_dump(empty("00")); // false,「00」不是 PHP 眼里的假
var_dump(empty("0.0")); // false
var_dump(empty([])); // true
var_dump(empty([0])); // false,数组里有元素
var_dump(empty("false")); // false,非空字符串等价记忆:empty($x) ≈ !isset($x) || !$x。
表单里没填的输入常常是 "",用 empty 能拦住;但用户真的输入了 0(数量、评分),empty 也会当成没填。这种字段用 isset + 严格比较,或 ?? 再判断 === ""。
对照表(建议动手跑一遍)
php
<?php
$samples = [
"未定义" => "missing",
"null" => null,
"false" => false,
"0" => 0,
'"0"' => "0",
'""' => "",
"[]" => [],
'"php"' => "php",
"1" => 1,
];
foreach ($samples as $label => $value) {
if ($label === "未定义") {
unset($tmp);
} else {
$tmp = $value;
}
echo sprintf(
"%-8s isset=%s is_null=%s empty=%s\n",
$label,
isset($tmp) ? "T" : "F",
// 未定义时 is_null 会 Warning,演示里用 @ 仅供对照,正式代码不要 @
@is_null($tmp) ? "T" : "F",
empty($tmp) ? "T" : "F",
);
}结果应当是:
| 值 | isset | is_null | empty |
|---|---|---|---|
| 未定义 | F | T(伴随 Warning) | T |
null | F | T | T |
false | T | F | T |
0 | T | F | T |
"0" | T | F | T |
"" | T | F | T |
[] | T | F | T |
"php" | T | F | F |
1 | T | F | F |
读这张表只记三句:
isset认「有货」:0、""、false都有货;null和没定义没有is_null只认null(没定义时会先报警,再当成null)empty认「布尔假」:上面所有假值 + 没定义
怎么选
| 你想问的问题 | 用 |
|---|---|
这个变量 / 键在不在,且不是 null? | isset |
这个(已存在的)值是不是 null? | === null(或 is_null) |
没填、空串、0、空数组……一律当没有? | empty(确认 0 也该被排除) |
缺了就用默认值,0 要保留? | ?? / ??=,见 三元运算符 |
数组键在不在,值是 null 也算在? | array_key_exists |
php
<?php
$page = $_GET["page"] ?? 1; // 缺键用 1;传了 0 会留下 0 再自己转换
$page = (int) $page;
$title = $_POST["title"] ?? "";
if ($title === "") {
echo "标题必填\n";
}
if (empty($_POST["agree"])) {
echo "请勾选同意\n"; // checkbox 没勾选时键不存在
}不要写 if (is_null($_GET["q"])) 来探测参数:没传时会 Warning。用 isset($_GET["q"]) 或 $_GET["q"] ?? null。
和 ??、?: 的关系
php
<?php
$zero = 0;
echo $zero ?? "兜底", "\n"; // 0,?? 只排除 null / 未定义
echo $zero ?: "兜底", "\n"; // 兜底,?: 把假值都换掉
echo empty($zero) ? "空" : "有", "\n"; // 空?? 更接近「isset 则用原值,否则默认」:$a ?? $b 在 $a 未定义或为 null 时取 $b,不会 Warning。多数读配置、读请求的场景,优先 ?? 而不是先 isset 再取值。
常见误区
用 empty 判断数量、ID。 empty(0) 为 true,库存为零会被当成「没这个字段」。
用 is_null 探测未定义或 $_GET 缺键。 PHP 8 会 Warning。改 isset 或 ??。
以为 isset($x) 等于 !is_null($x)。 变量已存在时两者相反;未定义时 isset 安静返回 false,is_null 报警。
以为 isset($arr["k"]) 能区分「没这个键」和「键的值是 null」。 两种都是 false。要区分用 array_key_exists。
empty("0") 为 true。 表单传来的数字全是字符串,"0" 会被 empty 吃掉。需要 0 合法时,写 $n === "" 或先转 int 再另判。
给 isset / empty 传函数返回值以外的「未定义」很安全,于是到处 empty。 能表达更精确的意图就更精确:缺省用 ??,空串用 === ""。
正式代码不要用 @is_null($x) 来吞 Warning,那是在掩盖问题。
已经用过的内置函数(速查)
| 函数 | 作用 |
|---|---|
var_dump() / print_r() | 调试打印 |
htmlspecialchars() | 输出到 HTML 前转义 |
count() | 数组元素个数 |
strlen() / mb_strlen() | 字节长度 / 字符长度(中文用 mb) |
implode() / explode() | 数组 ↔ 字符串 |
in_array() | 是否包含某值(第三个参数给 true) |
array_key_exists() | 键是否存在 |
sort() / array_merge() | 排序、合并,见 数组 |
filter_input() | 过滤请求参数,见 超全局变量 |
is_int() / is_string() / is_array() | 判断类型 |
gettype() | 返回类型名字符串 |
类型判断还有 is_null(),和 === null 选一个即可,本指南优先 === null。
更多函数按主题查手册,不必一次背完。用到字符串、文件、时间时再对手册抄参数。
书写建议
- 未定义可能发生的地方:
isset或??,不要is_null、不要直接读 - 已存在的值是不是
null:=== null empty只用于「假值都不要」且你接受"0"也算空- 新代码读数组键优先
$arr["k"] ?? $default - 查手册时看清返回值会不会是
false(很多找位置的函数找不到就返回false)
练习
- 对
$a分别为未赋值、null、0、"0"、""、"php",列出isset/empty的结果(is_null只对已赋值的测,避免 Warning)。 - 写一段:仅当
$_GET["q"]存在且不是null时打印它(用isset);缺省时打印无。不要触发 Undefined array key。 - 模拟表单
$qty = "0"(字符串零)。分别用empty($qty)和$qty === ""判断「没填」,解释哪一种会把合法的 0 件库存误判掉。 $user = ["name" => "小明", "bio" => null],对照isset、is_null($user["bio"])、array_key_exists("bio", $user)三个结果。
上一篇:变量的作用域