304 lines
No EOL
6.6 KiB
Markdown
304 lines
No EOL
6.6 KiB
Markdown
# PHP 代码检查样板和常见问题
|
||
|
||
## 目录
|
||
|
||
- [关键规则:仅检查特定文件](#关键规则仅检查特定文件)
|
||
- [常见 PHP 代码检查问题及修复](#常见-php-代码检查问题及修复)
|
||
- [译: 评论位置](#译-评论位置)
|
||
- [PSR-12 文件头部顺序](#psr-12-文件头部顺序)
|
||
- [包含故意违规的模拟类](#包含故意违规的模拟类)
|
||
- [多行条件对齐](#多行条件对齐)
|
||
- [未使用的闭包参数](#未使用的闭包参数)
|
||
- [数组和运算符对齐](#数组和运算符对齐)
|
||
- [缩进规则](#缩进规则)
|
||
- [修复 PHP 代码检查问题的工作流程](#修复-php-代码检查问题的工作流程)
|
||
- [快速命令参考](#快速命令参考)
|
||
|
||
## 关键规则:仅对特定文件进行代码检查
|
||
|
||
**切勿对整个代码库运行代码检查。** 始终仅对特定文件、已更改的文件或暂存的文件进行代码检查。
|
||
|
||
```bash
|
||
# ✅ 正确:仅在分支级别检查已更改的文件
|
||
pnpm lint:php:changes
|
||
|
||
# ✅ 正确:仅检查已暂存的更改文件
|
||
pnpm lint:php:changes:staged
|
||
|
||
# ✅ 正确:检查特定文件
|
||
pnpm lint:php -- path/to/file.php
|
||
pnpm lint:php:fix -- path/to/file.php
|
||
|
||
# ❌ 错误:检查整个代码库
|
||
pnpm lint:php
|
||
pnpm lint:php:fix
|
||
```
|
||
|
||
## 常见 PHP 代码检查问题与修复
|
||
|
||
### 快速参考表
|
||
|
||
| 问题 | 错误示例 | 正确示例 |
|
||
|-------|-------|---------|
|
||
| **译: 评论** | 在 return 前 | 在函数调用前 |
|
||
| **文件文档区块 (PSR-12)** | 在 `declare()` 后 | 在 `declare()` 前 |
|
||
| **缩进** | 使用空格 | 仅使用标签 |
|
||
| **数组对齐** | 不一致 | 根据上下文对齐 `=>` |
|
||
| **等于号对齐** | 不一致 | 匹配周围风格 |
|
||
|
||
## 译: 评论位置
|
||
|
||
译: 评论必须放在**翻译函数调用之前**,而不是 return 语句之前。
|
||
|
||
### 错误 - 评论在 return 前
|
||
|
||
```php
|
||
/* translators: %s: Gateway name. */
|
||
return sprintf(
|
||
esc_html__( '%s is not supported.', 'woocommerce' ),
|
||
'Gateway'
|
||
);
|
||
```
|
||
|
||
### 正确 - 在翻译函数前添加评论
|
||
|
||
```php
|
||
return sprintf(
|
||
/* translators: %s: 网关名称。 */
|
||
esc_html__( '%s 不受支持。', 'woocommerce' ),
|
||
'Gateway'
|
||
);
|
||
```
|
||
|
||
### 多个参数
|
||
|
||
```php
|
||
return sprintf(
|
||
/* translators: 1: 网关名称, 2: 国家代码。 */
|
||
esc_html__( '%1$s 在 %2$s 无法使用。', 'woocommerce' ),
|
||
$gateway_name,
|
||
$country_code
|
||
);
|
||
```
|
||
|
||
## PSR-12 文件顶部顺序
|
||
|
||
文件文档块必须位于 `declare()` 语句**前**,而不是之后。
|
||
|
||
### 错误 - 文档块在 declare() 后
|
||
|
||
```php
|
||
<?php
|
||
declare( strict_types=1 );
|
||
|
||
/**
|
||
* File docblock
|
||
*
|
||
* @package WooCommerce
|
||
*/
|
||
```
|
||
|
||
### 正确 - 在 declare() 前使用文档块
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* 文件文档块
|
||
*
|
||
* @package WooCommerce
|
||
*/
|
||
|
||
declare( strict_types=1 );
|
||
```
|
||
|
||
## 包含故意违规的模拟类
|
||
|
||
当创建必须匹配外部类名的模拟类时,请使用 phpcs:disable 注释:
|
||
|
||
```php
|
||
if ( ! class_exists( 'WC_Payments_Utils' ) ) {
|
||
/**
|
||
* 用于测试的模拟类。
|
||
*
|
||
* phpcs:disable Squiz.Classes.ClassFileName.NoMatch
|
||
* phpcs:disable Suin.Classes.PSR4.IncorrectClassName
|
||
* phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||
*/
|
||
class WC_Payments_Utils {
|
||
/**
|
||
* 模拟实现。
|
||
*/
|
||
public static function supported_countries() {
|
||
return array( 'US', 'GB' );
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 多行条件对齐
|
||
|
||
在多行条件中使用制表符进行续行对齐:
|
||
|
||
```php
|
||
// 正确 - 使用制表符进行续行
|
||
if ( class_exists( '\WC_Payments_Utils' ) &&
|
||
is_callable( '\WC_Payments_Utils::supported_countries' ) ) {
|
||
// code
|
||
}
|
||
|
||
// 同样正确 - 与左括号对齐
|
||
if ( class_exists( '\WC_Payments_Utils' ) &&
|
||
is_callable( '\WC_Payments_Utils::supported_countries' ) ) {
|
||
// code
|
||
}
|
||
```
|
||
|
||
## 未使用的闭包参数
|
||
|
||
当创建带有签名要求但未使用的参数闭包时,使用 `unset()` 来避免 PHPCS 错误:
|
||
|
||
### 问题
|
||
|
||
```php
|
||
// ❌ 错误 - PHPCS 错误:Generic.CodeAnalysis.UnusedFunctionParameter
|
||
'callback' => function ( string $return_url ) {
|
||
return array( 'success' => true );
|
||
},
|
||
```
|
||
|
||
### 解决方案
|
||
|
||
```php
|
||
// ✅ 正确 - 取消设置未使用的参数
|
||
'callback' => function ( string $return_url ) {
|
||
unset( $return_url ); // 避免参数未使用的 PHPCS 错误。
|
||
return array( 'success' => true );
|
||
},
|
||
```
|
||
|
||
### 多个未使用参数
|
||
|
||
```php
|
||
'callback' => function ( $arg1, $arg2, $arg3 ) {
|
||
unset( $arg1, $arg2 ); // 避免参数未使用的 PHPCS 错误。
|
||
return $arg3;
|
||
},
|
||
```
|
||
|
||
### 常见场景
|
||
|
||
- PHPUnit 测试中的模拟方法回调
|
||
- 签名固定的数组/过滤器回调
|
||
- 包含未使用参数的接口实现
|
||
|
||
**参考:** `tests/php/src/Internal/Admin/Settings/PaymentsRestControllerIntegrationTest.php:1647-1655`
|
||
|
||
## 数组和运算符对齐
|
||
|
||
### 数组箭头对齐
|
||
|
||
在每个数组上下文中一致地对齐 `=>` 箭头:
|
||
|
||
```php
|
||
// 正确 - 箭头已对齐
|
||
$options = array(
|
||
'gateway_id' => 'stripe',
|
||
'enabled' => true,
|
||
'country_code' => 'US',
|
||
);
|
||
|
||
// 也正确 - 短数组无需对齐
|
||
$small = array(
|
||
'id' => 123,
|
||
'name' => 'Test',
|
||
);
|
||
```
|
||
|
||
### 赋值运算符对齐
|
||
|
||
匹配周围代码风格:
|
||
|
||
```php
|
||
// 当周围代码对齐时,对齐:
|
||
$gateway_id = 'stripe';
|
||
$enabled = true;
|
||
$country_code = 'US';
|
||
|
||
// 当周围代码不对齐时,不对齐:
|
||
$gateway_id = 'stripe';
|
||
$enabled = true;
|
||
$country_code = 'US';
|
||
```
|
||
|
||
## 缩进规则
|
||
|
||
**总是使用制表符进行缩进,从不使用空格。**
|
||
|
||
```php
|
||
// ✅ 正确 - 使用制表符缩进
|
||
public function process_payment( $order_id ) {
|
||
→ $order = wc_get_order( $order_id );
|
||
→
|
||
→ if ( ! $order ) {
|
||
→ → return false;
|
||
→ }
|
||
→
|
||
→ return true;
|
||
}
|
||
|
||
// ❌ 错误 - 使用空格缩进
|
||
public function process_payment( $order_id ) {
|
||
$order = wc_get_order( $order_id );
|
||
|
||
if ( ! $order ) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
```
|
||
|
||
## 修复 PHP 代码检查问题的工作流程
|
||
|
||
1. **对更改的文件运行代码检查:**
|
||
|
||
```bash
|
||
pnpm lint:php:changes
|
||
```
|
||
|
||
2. **自动修复可以修复的问题:**
|
||
|
||
```bash
|
||
pnpm lint:php:fix -- path/to/file.php
|
||
```
|
||
|
||
3. **审查剩余错误** - 需要手动修复的常见问题:
|
||
- 译: 评论位置
|
||
- 文件文档区块顺序 (PSR-12)
|
||
- 未使用的闭包参数 (添加 `unset()`)
|
||
|
||
4. **手动处理剩余问题**
|
||
|
||
5. **验证输出是干净的:**
|
||
|
||
```bash
|
||
pnpm lint:php -- path/to/file.php
|
||
```
|
||
|
||
6. **提交**
|
||
|
||
## 快速命令参考
|
||
|
||
```bash
|
||
# 检查更改的文件
|
||
pnpm lint:php:changes
|
||
|
||
# 检查特定文件
|
||
pnpm lint:php -- src/Internal/Admin/ClassName.php
|
||
|
||
# 修复特定文件
|
||
pnpm lint:php:fix -- src/Internal/Admin/ClassName.php
|
||
|
||
# 检查并显示错误详情
|
||
vendor/bin/phpcs -s path/to/file.php
|
||
``` |