本文目录导读:

- 命名参数与代码对齐规则(PHP 8.0+)
- 属性(Property)与构造器提升(PHP 8.0+)
- Match 表达式格式(PHP 8.0+)
- 空数组与空字符串的多行简化(PER 2.0)
- 属性钩子(Property Hooks, PHP 8.4+)
- 联合类型与
null类型的空格规范(PHP 8.0+) - Readonly 属性格式(PHP 8.1+)
#[\Attribute]属性语法(PHP 8.0+)- 文件结束标记与严格类型声明
- 工具支持与自动化(推荐)
- 核心变化趋势
截至2025年5月,PHP最新的主要规范更新源自PHP-FIG(PHP Framework Interop Group)发布的PSR-12扩展版本(PSR-12是PSR-2的替代和扩展),以及PER(PHP Evolving Recommendation)工作组提出的PER Coding Style 2.0,PHP语言本身从8.0到8.4的演进也带来了与代码规范相关的变化(如属性、构造器提升等)。
以下是近期(2023-2025年)值得关注的代码规范更新要点(主要基于PER Coding Style 2.0及PHP 8.x特性实践):
命名参数与代码对齐规则(PHP 8.0+)
-
规范明确:使用命名参数时,参数名与 之间必须保留一个空格,
function foo(string $name = 'default', int $age = 0): void {} foo(name: 'John', age: 30); // 正确 foo(name:'John'); // 错误(冒号前无空格) -
多行对齐:当命名参数跨多行时,建议每个参数独占一行,且冒号对齐(非强制,但推荐):
$result = someFunction( name: 'Alice', age: 25, active: true, );
属性(Property)与构造器提升(PHP 8.0+)
-
构造器属性提升(Constructor Property Promotion)已完全纳入PER规范:
// 推荐写法 class User { public function __construct( private string $name, // 无多余空格 private int $age, ) {} } -
规则:
private/protected后跟一个空格- 变量名后无空格,冒号前无空格(
string $name) - 类型和变量名之间一个空格
- 多行参数时,参数类型对齐(如上面的
string和int对齐)
Match 表达式格式(PHP 8.0+)
-
match表达式被视为类似switch的控制结构,但格式要求更严格:match后必须有一个空格(与 之间)- 每个
=>前后各一个空格 - 最后一个分支后的逗号可以省略,但如果添加则必须紧跟表达式后
$result = match ($value) { // match 后空格 1 => 'one', 2 => 'two', default => 'other', // 最后一个逗号可选 };
空数组与空字符串的多行简化(PER 2.0)
-
简化空数组定义:允许 紧跟在 或 后,不强制换行:
// 允许 $items = []; // 也允许(但不鼓励如果后面有复杂结构) function foo(): array {} -
多行数组:如果数组元素跨多行,最后一个元素后必须跟一个逗号(trailing comma):
$config = [ 'host' => 'localhost', 'port' => 8080, // 末尾逗号必须,便于 diff ];
属性钩子(Property Hooks, PHP 8.4+)
-
这是PHP 8.4新特性(2024年11月发布),PER尚未明确规范,但社区已形成初步共识:
- 花括号 应放在类型声明同一行(类似方法定义)
set/get前各一个空格- 每个
set/get独占一行
class User { public string $name { set => ucfirst(strtolower($value)); get => strtoupper($this->name); } }
联合类型与 null 类型的空格规范(PHP 8.0+)
-
联合类型中 前后必须没有空格(此规则在PSR-12/PER 2.0中已明确):
// 正确 public function foo(string|int $value): void {} // 错误 public function foo(string | int $value): void {} -
交集类型(PHP 8.1+)同理:
A&B,前后无空格。
Readonly 属性格式(PHP 8.1+)
-
readonly关键字应放在可见性之后、类型之前:public readonly string $name; // 正确 readonly public string $name; // 不推荐
#[\Attribute] 属性语法(PHP 8.0+)
-
属性(Attributes)的 前必须有一个空格(如果前面有代码),但若独占一行则直接开始:
#[Route('/user')] // 文件顶部直接写 class UserController { #[Inject] public function __construct( #[Assert\NotBlank] // 属性与变量之间无空格 private string $name, ) {} }
文件结束标记与严格类型声明
-
文件末尾:PHP文件依然强烈建议省略
?>结束标记,尤其是纯PHP文件。 -
declare(strict_types=1):必须放在<?php之后、任何其他代码(包括命名空间)之前,且独占一行:<?php declare(strict_types=1); namespace App\Controller;
工具支持与自动化(推荐)
-
PHP-CS-Fixer (v3.x) 和 PHP_CodeSniffer (v3.x) 均已支持上述大部分规则。
-
建议在项目中配置
.php-cs-fixer.dist.php或phpcs.xml,并启用规则集:@PSR12@PER
// .php-cs-fixer.dist.php 示例 return (new PhpCsFixer\Config()) ->setRules([ '@PSR12' => true, 'trailing_comma_in_multiline' => ['elements' => ['arrays', 'arguments', 'parameters']], 'single_space_around_construct' => true, ]);
核心变化趋势
| 方面 | 旧规范(PSR-2/旧实践) | 新规范(PER/PSR-12扩展) |
|---|---|---|
| 命名参数 | 未定义 | 冒号前必须有空格,多行可对齐 |
| 构造器提升 | 未规范 | 推荐单行,类型和变量间一个空格 |
| Match 表达式 | 未涉及 | 类似switch,=> 前后空格 |
| 联合类型空格 | 无要求 | 前后无空格 |
| 属性钩子 | 不存在 | 花括号与类型同行(社区共识) |
| 末尾逗号 | 仅数组可选 | 多行数组/参数/命名参数推荐必须加逗号 |
| Readonly | 未出现 | 放在可见性之后类型之前 |
如果你在使用具体框架(如Laravel、Symfony),它们可能有更细化的团队规范,但以上内容代表了PHP社区公认的最新的核心风格更新。