isset()判变量是否声明且非null,empty()经类型转换后判空值(如0、"0"、[]、false均为空);校验参数应避免误用empty()过滤合法值,需结合isset()、类型断言及filter_var()等显式验证。

isset() 和 empty() 别混着用,先分清语义
isset() 只判断变量是否已声明且不为 null;empty() 会做类型转换后判“空值”,比如 0、"0"、[]、false 都算空。实际校验参数时,常因误用 empty() 把合法的 0 或字符串 "0" 当成非法值过滤掉。
- 接口接收分页参数
$page,用empty($page)会把page=0拒绝,但有些场景第 0 页是有效语义 - 校验必填字段,应优先用
isset($var) && $var !== '',而非!empty($var) - 若真需宽松判空(如用户昵称允许为 "0" 但不允许为空格或纯空白),得配合
trim()和strlen()
filter_var() 比正则和 type casting 更可靠
直接用 (int)$str 或 intval() 强转,遇到 "123abc" 会静默转成 123,丢失错误信号;手写正则又容易漏边界(比如没考虑 +123、科学计数法)。PHP 内置的 filter_var() 带验证逻辑和失败反馈:
- 验证邮箱:
filter_var($email, FILTER_VALIDATE_EMAIL),比preg_match('/^.+@.+..+$/', $email)准确得多 - 验证整数且范围可控:
filter_var($id, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) - 验证 URL:
filter_var($url, FILTER_VALIDATE_URL),能识别协议、主机名格式等细节
注意:FILTER<em>SANITIZE</em>* 系列是“清洗”不是“校验”,比如 FILTER_SANITIZE_NUMBER_INT 会删掉所有非数字字符,可能掩盖原始输入问题,校验阶段别用它替代验证。
数组结构校验别只查 key 存在,要验类型和嵌套
API 返回或接收的数组常有深层结构,仅用 isset($data['user']['profile']['age']) 不够——它不保证 $data['user'] 是数组,也不防 'age' 是字符串 "twenty-five"。
- 先用
is_array()逐层守门:isset($data['user']) && is_array($data['user']) && isset($data['user']['profile']) && is_array($data['user']['profile']) - 对关键字段加类型断言:
is_int($data['user']['profile']['age']) && $data['user']['profile']['age'] > 0 - 复杂结构建议封装成小函数,比如
require_int($data, 'user.profile.age', 1),内部做路径解析 + 类型检查 + 默认值 fallback
对象属性校验要防 __get() 和动态属性干扰
当对象启用了魔术方法 <strong>get()</strong>(如 Laravel 的 Model 或 Doctrine Entity),isset($obj->field) 可能返回 true 即使字段不存在,因为 get() 被触发并返回了默认值(如 null)。
- 校验是否真正定义了该属性,用
property_exists($obj, 'field'),它不触发__get() - 若需同时确认可访问且非空,拆成两步:
property_exists($obj, 'field') && $obj->field !== null - 对于 DTO 或严格模式对象,直接读属性前加
assert(isset($obj->field))并配合declare(strict_types=1),让类型错误提前暴露
PHP 变量校验的严谨性,往往卡在“你以为的空”和“它实际的值”之间那层隐式转换上。少依赖直觉,多走一步显式判断,尤其是 0、"0"、null、false 这几类值的边界行为。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











