现代 PHP 特性
本章将介绍 PHP 7 和 PHP 8 的新特性。
PHP 7 新特性
标量类型声明
<?php
declare(strict_types=1); // 严格模式
function add(int $a, int $b): int {
return $a + $b;
}
function greet(string $name): string {
return "Hello, $name";
}
function calculate(float $a, float $b): float {
return $a * $b;
}
function toggle(bool $flag): bool {
return !$flag;
}
?>
返回类型声明
<?php
function getUser(int $id): ?array {
// 返回数组或 null
return $users[$id] ?? null;
}
function process(): void {
// 无返回值
echo "处理完成";
}
function getItems(): array {
return [1, 2, 3];
}
?>
null 合并运算符
<?php
// PHP 7 之前
$name = isset($_GET['name']) ? $_GET['name'] : 'Guest';
// PHP 7+
$name = $_GET['name'] ?? 'Guest';
// 链式使用
$value = $a ?? $b ?? $c ?? 'default';
?>
太空船运算符
<?php
// <=> 返回 -1, 0, 1
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// 用于排序
$users = [
['name' => '张三', 'age' => 25],
['name' => '李四', 'age' => 20],
['name' => '王五', 'age' => 30]
];
usort($users, fn($a, $b) => $a['age'] <=> $b['age']);
?>
常量数组
<?php
const COLORS = ['red', 'green', 'blue'];
class Status {
const PENDING = 'pending';
const ACTIVE = 'active';
const INACTIVE = 'inactive';
const ALL = [self::PENDING, self::ACTIVE, self::INACTIVE];
}
?>
匿名类
<?php
$logger = new class {
public function log($message) {
echo "[LOG] $message\n";
}
};
$logger->log("测试消息");
// 实现接口
$comparable = new class implements Comparable {
public function compare($other): int {
return 0;
}
};
// 继承类
$extended = new class extends BaseClass {
// ...
};
?>
Closure::call()
<?php
class Person {
private $name;
public function __construct($name) {
$this->name = $name;
}
}
$getName = function() {
return $this->name;
};
$person = new Person("张三");
echo $getName->call($person); // 张三
?>
PHP 7.1 新特性
可空类型
<?php
function greet(?string $name): ?string {
return $name ? "Hello, $name" : null;
}
echo greet("张三"); // Hello, 张三
echo greet(null); // null
?>
void 返回类型
<?php
function logMessage(string $message): void {
echo $message;
// 不能有 return 语句
}
?>
多异常捕获
<?php
try {
// ...
} catch (InvalidArgumentException | RuntimeException $e) {
echo $e->getMessage();
}
?>
iterable 伪类型
<?php
function process(iterable $items): void {
foreach ($items as $item) {
echo $item;
}
}
process([1, 2, 3]);
process(new ArrayIterator([1, 2, 3]));
?>
PHP 7.2 新特性
object 类型
<?php
function process(object $obj): object {
return $obj;
}
?>
参数类型扩展
<?php
class ParentClass {
public function process(string $value) {}
}
class ChildClass extends ParentClass {
// PHP 7.2+ 允许放宽参数类型
public function process($value) {}
}
?>
PHP 7.3 新特性
灵活的 Heredoc/Nowdoc
<?php
// 之前必须顶格写结束标记
$str = <<<EOD
Hello
World
EOD; // PHP 7.3+ 允许缩进
echo $str;
?>
数组解构支持引用
<?php
$arr = [1, 2, 3];
[&$a, $b] = $arr;
$a = 10;
echo $arr[0]; // 10
?>
JSON_THROW_ON_ERROR
<?php
try {
$data = json_decode($json, false, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo $e->getMessage();
}
?>
PHP 7.4 新特性
箭头函数
<?php
$numbers = [1, 2, 3, 4, 5];
// 传统匿名函数
$squares = array_map(function($n) {
return $n * $n;
}, $numbers);
// 箭头函数
$squares = array_map(fn($n) => $n * $n, $numbers);
// 自动捕获外部变量
$multiplier = 10;
$result = array_map(fn($n) => $n * $multiplier, $numbers);
?>
类型化属性
<?php
class User {
public int $id;
public string $name;
public ?string $email = null;
private array $tags = [];
}
?>
null 合并赋值运算符
<?php
// 之前
$data['name'] = $data['name'] ?? 'default';
// PHP 7.4+
$data['name'] ??= 'default';
?>
`
### 数组展开运算符
```php
<?php
$a = [1, 2, 3];
$b = [4, 5, 6];
// 合并数组
$merged = [...$a, ...$b]; // [1, 2, 3, 4, 5, 6]
// 函数调用
function add($a, $b, $c) {
return $a + $b + $c;
}
$nums = [1, 2, 3];
echo add(...$nums); // 6
?>
PHP 8.0 新特性
命名参数
<?php
function createUser($name, $age = 18, $city = '北京') {
return compact('name', 'age', 'city');
}
// 传统调用
$user = createUser('张三', 25, '上海');
// 命名参数
$user = createUser(name: '张三', age: 25, city: '上海');
$user = createUser(name: '李四', city: '广州'); // 跳过默认参数
?>
注解(Attributes)
<?php
#[Attribute]
class Route {
public function __construct(public string $path, public string $method = 'GET') {}
}
class UserController {
#[Route('/users', 'GET')]
public function index() {}
#[Route('/users/{id}', 'GET')]
public function show(int $id) {}
}
// 读取注解
$reflection = new ReflectionMethod(UserController::class, 'index');
$attributes = $reflection->getAttributes(Route::class);
foreach ($attributes as $attr) {
$route = $attr->newInstance();
echo $route->path; // /users
}
?>
构造器属性提升
<?php
// 之前
class User {
public string $name;
public int $age;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
}
}
// PHP 8.0+
class User {
public function __construct(
public string $name,
public int $age,
public ?string $email = null
) {}
}
?>
match 表达式
<?php
$status = 200;
// switch
switch ($status) {
case 200:
case 300:
$message = '成功';
break;
case 400:
$message = '客户端错误';
break;
default:
$message = '未知';
}
// match
$message = match($status) {
200, 300 => '成功',
400, 404 => '客户端错误',
500, 502, 503 => '服务器错误',
default => '未知'
};
?>
Nullsafe 运算符
<?php
// 之前
$country = null;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
// PHP 8.0+
$country = $user?->getAddress()?->country;
?>
联合类型
<?php
function process(int|float $number): int|float {
return $number * 2;
}
function format(string|int $value): string {
return (string) $value;
}
?>
mixed 类型
<?php
function process(mixed $value): mixed {
return $value;
}
?>
throw 表达式
<?php
// 之前
$value = $config['key'];
if ($value === null) {
throw new Exception('配置不存在');
}
// PHP 8.0+
$value = $config['key'] ?? throw new Exception('配置不存在');
// 在箭头函数中使用
$getValue = fn() => throw new Exception('不支持');
?>
PHP 8.1 新特性
枚举
<?php
enum Status {
case Pending;
case Active;
case Inactive;
}
// 带值枚举
enum HttpStatus: int {
case OK = 200;
case NotFound = 404;
case ServerError = 500;
}
// 使用
function updateStatus(Status $status): void {
match($status) {
Status::Pending => echo '待处理',
Status::Active => echo '激活',
Status::Inactive => echo '未激活',
};
}
echo HttpStatus::OK->value; // 200
?>
readonly 属性
<?php
class User {
public readonly int $id;
public readonly string $name;
public function __construct(int $id, string $name) {
$this->id = $id;
$this->name = $name;
}
}
$user = new User(1, '张三');
// $user->name = '李四'; // 错误:不能修改只读属性
?>
never 返回类型
<?php
function redirect(string $url): never {
header("Location: $url");
exit();
}
function throwError(string $message): never {
throw new Exception($message);
}
?>
final 常量
<?php
class BaseClass {
final public const IMPORTANT = 'value';
}
class ChildClass extends BaseClass {
// public const IMPORTANT = 'new value'; // 错误:不能覆盖
}
?>
交集类型
<?php
interface Runnable {
public function run(): void;
}
interface Jumpable {
public function jump(): void;
}
function process(Runnable&Jumpable $obj): void {
$obj->run();
$obj->jump();
}
?>
PHP 8.2 新特性
readonly 类
<?php
readonly class User {
public function __construct(
public string $name,
public int $age
) {}
}
// 所有属性自动为 readonly
?>
枚举属性
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
public function label(): string {
return match($this) {
self::Pending => '待处理',
self::Active => '已激活',
};
}
}
echo Status::Pending->label(); // 待处理
?>
随机数扩展
<?php
$rng = new Random\Randomizer();
echo $rng->getInt(1, 100);
echo $rng->getBytes(16);
$items = ['a', 'b', 'c'];
$shuffled = $rng->shuffleArray($items);
$picked = $rng->pickArrayKeys($items, 2);
?>
PHP 8.3 新特性
类型化类常量
<?php
class Status {
const string PENDING = 'pending';
const int MAX_ATTEMPTS = 3;
}
?>
json_validate 函数
<?php
if (json_validate($jsonString)) {
$data = json_decode($jsonString);
}
?>
Dynamic class constant fetch
<?php
class Status {
const PENDING = 'pending';
}
$name = 'PENDING';
echo Status::{$name}; // pending
?>
小结
本章我们学习了:
- PHP 7:标量类型、返回类型、null 合并运算符、太空船运算符
- PHP 7.1:可空类型、void、多异常捕获
- PHP 7.4:箭头函数、类型化属性、数组展开
- PHP 8.0:命名参数、注解、match、nullsafe 运算符、联合类型
- PHP 8.1:枚举、readonly、never
- PHP 8.2/8.3:readonly 类、类型化常量
下一章我们将学习常用标准库。