拥抱当今的 PHP:严格类型、箭头函数、nullsafe 运算符、枚举,以及 match 表达式。
在 Kodokon 中打开本课现代 PHP 拥抱类型。declare(strict_types=1) 放在文件的第一条语句处,会禁用隐式转换:把字符串 '10' 传给一个 float 参数会抛出一个 TypeError,而不是被悄悄地转换。请为参数和返回值标注类型:这样你的错误会及早地、在正确的位置浮现出来,而不是拖到三个文件之后。
<?php
declare(strict_types=1);
function applyDiscount(
float $price,
float $rate = 0.1
): float {
return round($price * (1 - $rate), 2);
}
echo applyDiscount(49.99);
echo PHP_EOL;
echo applyDiscount(100.0, 0.25);箭头函数 fn 把只有单个表达式的匿名函数浓缩了起来。相比传统闭包,它有一个重大优势:它会自动捕获父作用域的变量,无需 use 子句。它们在配合 array_map() 和 array_filter() 时格外出彩。
<?php
declare(strict_types=1);
$prices = [12.5, 49.9, 8.0, 120.0];
$rate = 0.2;
$discounted = array_map(
fn (float $p): float => round($p * (1 - $rate), 2),
$prices
);
$affordable = array_filter(
$discounted,
fn (float $p): bool => $p < 50
);
print_r($affordable);nullsafe 运算符 ?-> 会在链条中的某一环为 null 时立刻短路整个调用,而不是引发一个致命错误。与 ?? 结合使用,它能用一行清晰易读的代码取代层层嵌套的 if 语句金字塔。
<?php
declare(strict_types=1);
class Address
{
public function __construct(
public readonly string $city
) {
}
}
class User
{
public function __construct(
public readonly ?Address $address = null
) {
}
}
$alice = new User(new Address('Lyon'));
$bob = new User();
echo $alice->address?->city ?? 'Unknown city';
echo PHP_EOL;
echo $bob->address?->city ?? 'Unknown city';枚举为封闭的取值集合(各种状态、角色)赋予了真正的类型:创建一个不存在的状态变得不可能。而 match 相比 switch 是一次明显的改进:严格比较、把结果作为一个值返回,以及在没有任何分支匹配时抛出 UnhandledMatchError - 这是一道防止疏漏的保险。
<?php
declare(strict_types=1);
enum OrderStatus: string
{
case Pending = 'pending';
case Shipped = 'shipped';
case Delivered = 'delivered';
public function label(): string
{
return match ($this) {
self::Pending => 'Pending',
self::Shipped => 'Shipped',
self::Delivered => 'Delivered',
};
}
}
$status = OrderStatus::from('shipped');
echo $status->label();