true / false / null 独立类型
概述
自 PHP 8.2 起,true、false 和 null 可以作为独立的类型用于类型声明。在此之前,false 和 null 只能出现在联合类型中(如 int|null 或 int|false)。true 则是全新的类型。
独立类型的引入使得 PHP 的类型系统更加完备,允许你精确地将参数、返回值或属性约束为只能是 true、false 或 null。
核心要点
true和false独立类型自 PHP 8.2 起可用。null独立类型自 PHP 8.2 起可用(之前只能通过?T或T|null使用)。true和false不能同时出现在联合类型中,应使用bool代替。- 独立类型主要用于参数类型约束和返回值声明,提供更精确的类型安全。
- :::
基础概念
什么是独立类型
在 PHP 8.2 之前,null 和 false 只能作为联合类型的一部分或通过 ? 语法糖使用。PHP 8.2 将它们提升为独立的一等类型,可以直接单独声明。
| 类型 | PHP 版本 | 说明 |
|---|---|---|
bool | 全版本 | 可为 true 或 false |
true | 8.2+ | 只能为 true |
false | 8.2+ | 只能为 false |
null | 8.2+ | 只能为 null |
?T | 7.1+ | 等价于 T|null |
独立类型与 bool / Null 的区别
| 声明 | 接受的值 | 场景 |
|---|---|---|
bool | true 或 false | 通用的布尔参数 |
true | 仅 true | 确保参数必须为 true |
false | 仅 false | 确保参数必须为 false |
null | 仅 null | 确保参数必须为 null |
?string | string 或 null | 可空的字符串 |
语法与代码示例
true 独立类型
<?php
declare(strict_types=1);
// 参数必须为 true
function enableFeature(bool $feature, true $confirm): void
{
if ($feature) {
echo "Feature enabled" . PHP_EOL;
}
}
// 错误调用
enableFeature(true, false); // TypeError: confirm 必须为 true
// 正确调用
enableFeature(true, true); // OK
// 返回类型必须为 true
function alwaysReturnsTrue(): true
{
return true; // OK
}
// function alwaysReturnsTrue(): true
// {
// return false; // TypeError: Return value must be true
// }false 独立类型
<?php
declare(strict_types=1);
// 函数返回 false 表示失败
function isFailure(int $statusCode): false
{
return false; // OK
}
// 在联合类型中使用 false(PHP 8.0+ 的经典用法)
function strposWrapper(string $haystack, string $needle): int|false
{
$result = strpos($haystack, $needle);
return $result; // 返回 int 或 false
}
// false 作为独立类型用于参数
function setStrictMode(false $disableStrict): void
{
echo "Strict mode is disabled" . PHP_EOL;
}null 独立类型
<?php
declare(strict_types=1);
// 参数必须为 null
function resetValue(null $reset): void
{
echo "Value has been reset to null" . PHP_EOL;
}
// 错误调用
resetValue("hello"); // TypeError
// 正确调用
resetValue(null); // OK
// 属性声明为 null
class Configuration
{
public null $defaultValue = null;
public string|null $optionalValue = null;
}在联合类型中使用独立类型
<?php
declare(strict_types=1);
// 返回值只能是 string 或 false(PHP 8.0+ 就支持)
function findFile(string $filename): string|false
{
if (file_exists($filename)) {
return file_get_contents($filename);
}
return false;
}
// 返回值只能是 string 或 null
function getEnvVar(string $name): string|null
{
return getenv($name); // 返回 string 或 false,但类型声明只接受 string|null
}
// 返回值只能是 true 或 null
function checkPermission(string $role): true|null
{
if ($role === 'admin') {
return true;
}
return null;
}详细说明
true 和 false 不能同时出现在联合类型中
PHP 不允许同时使用 true 和 false,因为 true|false 等价于 bool,直接使用 bool 即可:
<?php
declare(strict_types=1);
// 错误:不能同时使用 true 和 false
function bad(bool $value): true|false {} // Fatal Error
// 正确:使用 bool
function good(bool $value): bool {}PHP 8.2 之前的限制
在 PHP 8.2 之前,以下类型声明是非法的:
<?php
declare(strict_types=1);
// PHP 8.2 之前的错误用法
function acceptsNull(null $value): void {} // Fatal Error (PHP < 8.2)
function acceptsFalse(false $value): void {} // Fatal Error (PHP < 8.2)
function returnsNull(): null {} // Fatal Error (PHP < 8.2)
function returnsFalse(): false {} // Fatal Error (PHP < 8.2)
// PHP 8.0+ 的等价写法
function acceptsNullFallback(?int $value): void {} // 只能通过 ?Type 实现
function returnsFalseFallback(): int|false {} // 只能在联合类型中使用独立类型的冗余检查
PHP 在编译时会检测类型冗余,避免简单的逻辑错误:
<?php
declare(strict_types=1);
// 以下均会报错
function bad1(): bool|true {} // bool 已包含 true,true 冗余
function bad2(): bool|false {} // bool 已包含 false,false 冗余
function bad3(): true|false {} // 等价于 bool,应直接用 bool
function bad4(): int|null|true {} // 如果使用 bool 则 true 冗余独立类型与可空类型的对比
<?php
declare(strict_types=1);
// null 独立类型:只接受 null
function acceptsExactlyNull(null $value): void
{
echo "Got null" . PHP_EOL;
}
// 可空类型:接受特定类型或 null
function acceptsStringOrNull(?string $value): void
{
echo "Got: " . ($value ?? 'null') . PHP_EOL;
}
acceptsExactlyNull(null); // OK
acceptsExactlyNull("hello"); // TypeError
acceptsStringOrNull(null); // OK
acceptsStringOrNull("hello"); // OK
acceptsStringOrNull(42); // TypeError实战示例
使用 true 类型的布尔开关
<?php
declare(strict_types=1);
class FeatureFlag
{
private array $flags = [
'dark_mode' => false,
'beta_api' => false,
];
// 使用 true 参数确保只能开启,不能关闭
public function enable(string $flag, true $confirmed): void
{
if (!isset($this->flags[$flag])) {
throw new InvalidArgumentException("Unknown flag: {$flag}");
}
$this->flags[$flag] = true;
}
// 使用 false 参数确保只能关闭,不能开启
public function disable(string $flag, false $confirmed): void
{
if (!isset($this->flags[$flag])) {
throw new InvalidArgumentException("Unknown flag: {$flag}");
}
$this->flags[$flag] = false;
}
public function isEnabled(string $flag): bool
{
return $this->flags[$flag] ?? false;
}
}
$features = new FeatureFlag();
$features->enable('dark_mode', true);
$features->disable('dark_mode', false);
// $features->enable('dark_mode', false); // TypeError使用 null 独立类型的重置机制
<?php
declare(strict_types=1);
class UserPreferences
{
private array $settings = [
'theme' => 'light',
'language' => 'zh-CN',
'timezone' => 'Asia/Shanghai',
];
// null 独立类型表示"重置为默认"
public function resetSetting(string $key, null $confirm): void
{
$defaults = [
'theme' => 'light',
'language' => 'zh-CN',
'timezone' => 'Asia/Shanghai',
];
$this->settings[$key] = $defaults[$key];
}
public function updateSetting(string $key, string $value): void
{
$this->settings[$key] = $value;
}
public function getSetting(string $key): string
{
return $this->settings[$key];
}
}
$prefs = new UserPreferences();
$prefs->updateSetting('theme', 'dark');
$prefs->resetSetting('theme', null);使用 false 作为返回值标记失败
<?php
declare(strict_types=1);
interface RepositoryInterface
{
/**
* 查找记录
* @return array 成功时返回数据
* @return false 失败时返回 false
*/
public function findById(int $id): array|false;
}
class UserRepository implements RepositoryInterface
{
public function findById(int $id): array|false
{
$result = $this->query("SELECT * FROM users WHERE id = ?", [$id]);
if ($result === null) {
return false;
}
return $result;
}
private function query(string $sql, array $params): ?array
{
// 模拟数据库查询
return null;
}
}注意事项
独立类型的适用场景
独立类型 true、false、null 并不适用于所有场景。它们最适合以下情况:
| 场景 | 是否适合 | 原因 |
|---|---|---|
布尔参数需要确保只能是 true | 适合 | 防止误传 false |
| 函数返回值用于标记成功/失败 | 适合 | false 明确表示失败 |
需要将参数约束为仅 null | 较少使用 | 通常用 ?Type 更合适 |
| 通用的布尔参数 | 不适合 | 应使用 bool |
| 可空参数 | 不适合 | 应使用 ?Type |
PHP 版本兼容性
<?php
declare(strict_types=1);
// PHP 8.0+ 可用:false 在联合类型中
function find(): string|false {}
// PHP 8.2+ 可用:false/null/true 作为独立类型
function acceptTrue(true $v): void {}
function acceptFalse(false $v): void {}
function acceptNull(null $v): void {}
function returnTrue(): true {}
function returnFalse(): false {}
function returnNull(): null {}最佳实践
在联合类型中优先使用
false而非null表示失败:PHP 内置函数(如strpos、file_get_contents)广泛使用false表示失败,保持一致性。谨慎使用
true和null独立类型:这些类型使用场景相对有限,过度使用可能降低代码可读性。true类型适合"确认"参数:当布尔参数需要确保只能是true时(如操作确认、特性启用),使用true类型可以防止误传false。不要用
true|false替代bool:true|false是非法的,PHP 会报错。直接使用bool类型。在联合类型中善用
false:string|false、int|false等联合类型在表示"成功返回值或失败标记"时非常实用。配合严格模式使用:独立类型在
declare(strict_types=1)下更加可靠,确保类型安全。