当前位置: 首页 > news >正文

PHP 现代特性速查 写出更简洁安全的代码(第一篇)

PHP 现代特性速查 写出更简洁安全的代码(第一篇)

基础你肯定掌握了。这个三部曲写给每天写 PHP 的人,帮你把代码写得更清楚、bug 更少、跑得更快。上篇讲那些能改变 API、DTO 和调用方式的现代特性。

默认你在用 PHP 8.x+。例子都很短,直接扔进 Laravel service 或普通 PHP 文件就能跑。

原文链接 PHP 现代特性速查 写出更简洁安全的代码(第一篇)

Attributes — 声明式、可发现的元数据(PHP 8.0)

替代了什么:脆弱的 docblock 和注解解析。

示例

#[Route(path: '/users', methods: ['GET'])]
class UserController { /* ... */ }

效果:反射读 attribute,启动时自动注册路由。IDE 能看到这些元数据,静态分析也能识别。

建议:attributes 适合框架接线(路由、验证、序列化),保持简单——复杂配置还是老实用 DTO。

Named Arguments — 自解释的函数调用(PHP 8.0)

替代了什么:容易搞错顺序的长参数列表。

示例

function connect(string $host, int $port, bool $tls = false) { /* ... */ }// 更清晰,顺序无关
connect(port: 5432, host: 'db.internal', tls: true);

效果:调用像配置文件一样好读;加可选参数也不会破坏兼容性。

建议:工厂方法和 HTTP 客户端配置最适合——配合 readonly DTO 做不可变配置。

Constructor Property Promotion — 减少 service 和 DTO 的样板代码(PHP 8.0)

替代了什么:重复的属性声明和赋值。

示例

class Mailer {public function __construct(private LoggerInterface $log,private CacheInterface $cache) {}
}

效果:构造函数简洁,打字少了拼写错误也少,属性自动带类型和注入。

建议:小 service 和 DTO 用这个——构造函数参数多了还是老实写工厂或 builder。

类型化属性(Typed Properties)— 尽早强制契约(PHP 7.4)

替代了什么:松散的 @var docblock 和混乱的 mixed 类型。

示例

class Order {public int $id;public ?DateTimeImmutable $shippedAt = null;
}

效果:赋错类型立刻抛 TypeError——领域 bug 早发现。

建议:配合静态分析(PHPStan/Psalm)在 CI 阶段就把问题拦住。

联合类型(Union Types)— 明确、灵活的 API(PHP 8.0)

替代了什么:模糊的 mixed 和不明确的类型提示。

示例

function find(string|int $id): ?User { /* ... */ }

效果:函数签名明确写出接受什么类型;静态工具能验证调用。

建议:union 要有意义——别动不动就 string|int|float|bool,除非真需要。

交叉类型(Intersection Types)— 更严格的多能力契约(PHP 8.1)

替代了什么:运行时检查对象是否实现多个接口。

示例

function process(Reader&Logger $obj) {// $obj 同时是 Reader 和 Logger
}

效果:编译时就能保证对象有你要的能力。

建议:装饰器和适配器最适合,确保它们同时满足多个接口。

Enums — 用领域安全的值替代魔法字符串(PHP 8.1)

替代了什么:容易出错的常量和字符串。

示例

enum PaymentStatus: string {case PENDING = 'pending';case PAID    = 'paid';case FAILED  = 'failed';
}$status = PaymentStatus::PAID;

效果:match 能穷举所有情况、重构更安全、日志也更清楚。

建议:持久化用 backed enums(string/int);常见的领域逻辑直接写在 enum 方法里。

只读属性和只读类(Readonly)— 不可变 DTO(属性:PHP 8.1;类:PHP 8.2)

替代了什么:手写的不可变对象和意外的变更 bug。

示例

readonly class UserDTO {public function __construct(public int $id,public string $email) {}
}

效果:构造完就不能改了——事件、配置、API 响应都适合。

建议:跨进程传的数据(队列、事件)优先用 readonly。

一等公民可调用对象(First-class Callables)— 简洁、零样板的回调(PHP 8.1)

替代了什么:冗长的匿名函数或基于字符串的 callable。

示例

$upper = strtoupper(...);
$names = array_map($upper, ['alice','bob']);

效果:管道好读,开销小。

建议:配合 array_map/array_filter 用,意图清楚。不需要捕获变量时别用闭包。

组合使用:真实例子

假设写个控制器动作,把这些特性组合起来:

#[Route(path: '/orders', methods: ['POST'])]
final class CreateOrderAction {public function __construct(private OrderService $service,private LoggerInterface $logger) {}public function __invoke(CreateOrderDTO $dto): JsonResponse {$order = $this->service->create($dto);$this->logger->info('order.created', ['id' => $order->id]);return new JsonResponse(['id' => $order->id], 201);}
}

这段代码把 attributes(路由)、constructor promotion(注入)、readonly DTO(不可变)、typed properties 和 enums(领域安全)组合在一起,代码简洁、一看就懂、还更安全。

高级技巧 — 老手怎么组合这些特性

验证管道:DTO + attributes + 静态分析,能在编译期验证的就别等运行时。

领域值对象:少用松散数组,多用小 readonly 值对象——类型化属性能帮你挡住下游的 bug。

Match + Enums:别用布尔标志和字符串 switch 了,enum 配 match 穷举,编译器帮你找漏掉的分支。

交叉类型给适配器:适配器要同时实现 Cacheable&Loggable 才能传给基础设施。

一等公民可调用对象优化 map:没有闭包分配开销,快一点也清楚一点。

什么时候别用这些特性(注意事项)

attributes 太多会拖慢反射 — 做接线可以,别在字段上堆一堆元数据。

Named arguments 在 DI 容器里可能出问题 — 调用时用它提升可读性没问题,写库给别人用就别这么干。

到处 readonly 开发时很烦 — DTO 和事件用 readonly 有意义,service 对象就别折腾了。

升级路线

还在 PHP < 7.4:先升到 7.4,类型化属性值得。

想提升生产力:直接上 8.1(enums、只读属性、一等公民可调用对象、交叉类型)。

8.2 加了只读类和其他改进——有用但不急。

最后

这些特性不是玩具,它们改变你建模数据、强制约束、理解系统的方式。用好了,attributes、enums、类型化属性能让代码更稳、团队更快。

代码库还在用魔法字符串、靠 docblock 或到处传可变数组?选一个特性(enums 或 readonly DTO)先迁移一个模块试试。效果好了,后面就好办了。

准备用哪个特性?说说你的痛点,我帮你找投入小、收益大的改法。

http://www.gsyq.cn/news/39189.html

相关文章:

  • 前小米高管创业,融资近2亿元,要做AI影像消费硬件丨智能涌现独家
  • AI元人文:核心工作路径(共三篇)
  • Java代码开发规范(基于Claude Code与Google Java Style Guide)
  • 读浪潮将至05更广泛的浪潮
  • [openwrt] openwrt换成清华源后,SSL verify error: unknown error
  • [OpenWRT/LEDE] a short history of OpenWRT
  • 生成式模型分类
  • 2025年11月学生平板品牌对比榜:新课标适配与错题管理实力榜
  • 2025年11月学生平板品牌评测:读书郎T5系列与四款竞品实力排行
  • 2025年11月适合小学生的学习机品牌推荐:热门机型排行与实测
  • 2025年11月卖得好的学习机品牌推荐:市场榜五强评测
  • AI元人文:价值权衡的计算理论与共识涌现新范式
  • 2025年北京股权纠纷律师事务所权威推荐榜:股权转让/股东争议/公司控制权纠纷专业律师团队精选
  • 2025年北京遗产继承律师事务所权威推荐榜:专业遗嘱继承、房产继承、涉外继承法律服务团队深度解析
  • 2025年北京婚姻家事律师事务所权威推荐榜:专业离婚诉讼、财产分割、子女抚养法律服务机构精选
  • 【AI说Rust 02】如何在 windows11 系统搭建 Rust 开发环境
  • 2025年11月优质太空舱铝板供应商排名:工厂实力与用户评价深度解析
  • 2025年11月太空舱铝板供应商排名:专业对比与实地考察报告
  • 接口实现C#泛型四则运算
  • [Flink/Hologres/汽车] 骋在数据洪流上:Flink+Hologres驱动零跑科技实时计算的应用与实践 [转]
  • 读《Python神经网络编程(异步图书) 塔里克拉希德》有感
  • 【CI130x 离在线】Python使用import opuslib 报错解决方案
  • 蒟蒻的S游记碎碎念
  • 【python刷题记录】移动零-双指针-简单
  • 002 vue3-admin项目的目录及文件说明之public目录
  • Day11CSS特性
  • Maya 2025软件超详细下载安装教程(附安装包和激活步骤)
  • 一款基于 .NET WinForm 开源、轻量且功能强大的节点编辑器,采用纯 GDI+ 绘制无任何依赖库仅仅100+Kb!
  • docker compose.yaml配置
  • Multisim保姆级图文下载安装教程包含下载、安装、汉化、激活