PHP 类型系统与严格模式
PHP 的类型系统经历过重大演变,从动态类型逐渐增加了静态类型特性,严格模式是这一演进中的关键特性。

类型系统基础
弱类型(默认模式)
// PHP 默认是弱类型,会自动进行类型转换
function add($a, $b) {
return $a + $b;
}
echo add("5", 3); // 8 - 字符串自动转为整数
echo add("5 apples", 3); // 8 - "5 apples" 转为 5
echo add("hello", 3); // 3 - "hello" 转为 0
类型声明(PHP 7+)
// 参数类型声明
function calculate(int $a, float $b): float {
return $a * $b;
}
// 默认模式下仍会尝试类型转换
echo calculate("5", 2.5); // 12.5 - "5" 转为整数 5
严格模式
启用严格模式
<?php
declare(strict_types=1);
// 现在类型必须严格匹配
function add(int $a, int $b): int {
return $a + $b;
}
// add("5", 3); // TypeError: 参数 1 必须是整数,字符串给定
add(5, 3); // 8 - 正确
严格模式的特性
- 作用域:基于文件级别,每个文件需要单独声明
- 继承影响:子类方法必须与父类保持相同的严格性
- 类型检查:不会进行隐式类型转换
支持的类型声明
declare(strict_types=1);
// 基本类型
function basicTypes(
int $int,
float $float,
string $string,
bool $bool,
array $array,
callable $callable
): void {}
// 特殊类型
function specialTypes(
mixed $mixed, // PHP 8.0+ - 任意类型
never $never, // PHP 8.1+ - 永不返回
void $void, // 无返回值
null $null, // 仅允许 null
false $false, // PHP 8.0+ - 仅允许 false
true $true, // PHP 8.2+ - 仅允许 true
): void {}
// 对象类型
function objectTypes(
stdClass $object, // 特定类名
object $objectType, // PHP 7.2+ - 任何对象
iterable $iterable, // PHP 7.1+ - 数组或 Traversable
): void {}
联合类型与交叉类型
declare(strict_types=1);
// 联合类型 (PHP 8.0+)
function processInput(int|string|array $input): void {
if (is_int($input)) {
echo "整数: $input";
} elseif (is_string($input)) {
echo "字符串: $input";
} else {
echo "数组";
}
}
// 可空联合类型
function findUser(int|null $id): ?string {
if ($id === null) {
return null;
}
return "User #$id";
}
// 交叉类型 (PHP 8.1+)
interface Loggable {
public function log(): void;
}
interface Serializable {
public function serialize(): string;
}
function processLoggableSerializable(Loggable&Serializable $item): void {
$item->log();
echo $item->serialize();
}
伪类型与内置类型
declare(strict_types=1);
// mixed - PHP 8.0+
function mixedExample(mixed $data): mixed {
return match(true) {
is_string($data) => strtoupper($data),
is_int($data) => $data * 2,
default => null
};
}
// never - 永远不会返回值
function throwException(string $message): never {
throw new \RuntimeException($message);
}
// void
function logMessage(string $message): void {
echo "[LOG] $message" . PHP_EOL;
// 不能有 return 语句(除非 return; 没有值)
}
类型推断与类型系统特性
declare(strict_types=1);
// 属性类型声明 (PHP 7.4+)
class User {
public string $name;
protected int $age;
private array $roles;
public ?DateTimeImmutable $createdAt = null;
// 只读属性 (PHP 8.1+)
public readonly string $email;
public function __construct(
string $name,
int $age,
string $email
) {
$this->name = $name;
$this->age = $age;
$this->email = $email;
}
}
// 返回类型推断
class Calculator {
public function add(int $a, int $b): static { // PHP 8.0+
$result = new static();
$result->value = $a + $b;
return $result;
}
private int $value = 0;
}
// 泛型风格 (通过 PHPDoc)
/** @template T */
class Collection {
/** @var array<int, T> */
private array $items = [];
/** @param T $item */
public function add(mixed $item): void {
$this->items[] = $item;
}
/** @return T */
public function get(int $index): mixed {
return $this->items[$index] ?? null;
}
}
// 使用方式
$users = new Collection();
$users->add(new User('Alice', 30, 'alice@example.com'));
$user = $users->get(0); // User|null
类型转换与注意事项
declare(strict_types=1);
// 安全的类型转换
function safeConversion(): void {
// 显式转换
$intValue = (int) "123"; // 123
$floatValue = (float) "3.14"; // 3.14
$stringValue = (string) 123; // "123"
$boolValue = (bool) 1; // true
// 类型转换函数
$intval = intval("456"); // 456
$floatval = floatval("7.89"); // 7.89
$strval = strval(true); // "1"
}
// 严格模式下的常见陷阱
function strictTraps(): void {
// 1. 除法总是返回 float 或 int
$result = 10 / 3; // 3.3333333333333 (float)
$result = 10 / 5; // 2.0 (float)
$result = intdiv(10, 3); // 3 (整数除法)
// 2. 字符串连接
$message = "Count: " . 5; // 总是字符串
}
// 类型判断
function typeChecking(mixed $value): string {
return match(true) {
is_int($value) => 'integer',
is_float($value) => 'float',
is_string($value) => 'string',
is_bool($value) => 'boolean',
is_array($value) => 'array',
is_object($value) => 'object: ' . get_class($value),
is_null($value) => 'null',
is_resource($value) => 'resource',
default => 'unknown'
};
}
最佳实践
declare(strict_types=1);
// 1. 始终使用严格模式
<?php
declare(strict_types=1);
// 你的代码...
// 2. 为所有函数和方法的参数和返回值添加类型声明
function createUser(string $name, string $email, int $age): User {
// 实现
}
// 3. 使用 nullable 类型表示可能为 null 的值
function findById(int $id): ?User {
// 实现
}
// 4. 使用联合类型增加灵活性
function formatValue(int|float|string $value): string {
// 实现
}
// 5. 使用 readonly 属性确保不变性
class Config {
public readonly array $settings;
public function __construct(array $settings) {
$this->settings = $settings;
}
}
// 6. 使用 value object 替代原始类型
class Email {
public readonly string $value;
public function __construct(string $email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException("Invalid email");
}
$this->value = $email;
}
}
性能考虑
严格模式下的类型检查会带来轻微的性能开销,但通常可以忽略不计,实际收益包括:
- 更早的错误发现:在开发阶段就能发现问题
- 更好的 IDE 支持:代码补全和类型提示更准确
- 自文档化:类型声明本身就是文档
- 更可靠的代码:减少类型相关的 bug
PHP 的类型系统已经从弱类型演变为具有丰富类型特性的语言,严格模式是 PHP 现代开发中的最佳实践,能显著提高代码质量和可维护性,建议在新项目中始终启用严格模式,并充分利用 PHP 提供的类型系统特性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播