PHP项目团队协作规范

wen PHP项目 2

PHP 项目团队协作规范

代码规范

1 PSR 标准遵循

  • 必须遵循 PSR-1(基础编码规范)和 PSR-12(扩展编码规范)
  • 推荐使用 PSR-4 自动加载标准
  • 统一 PHP 版本(如 PHP 8.1+),禁止使用废弃函数

2 命名规范

类型 规范 示例
类名 大驼峰(StudlyCase) UserService
方法名 小驼峰(camelCase) getUserList()
变量名 小驼峰或蛇形 $userName / $user_data(选其一,团队统一)
常量 大写+下划线 MAX_RETRY_COUNT
数组键 蛇形(推荐) ['user_name' => '张三']
文件名 大驼峰(类文件) UserService.php
数据库表 复数蛇形 usersorder_items
数据库字段 蛇形 created_at

3 代码风格要求

  • 缩进统一使用 4个空格(不使用 Tab)
  • 单行代码不超过 120字符
  • 每个 PHP 文件 必须以 <?php 开头,文件末尾 不保留闭合标签 ?>
  • 类的大括号须另起一行(PSR-12),控制结构的大括号与关键字同行
  • 不使用 echo 输出 HTML(应使用模板引擎)
<?php
declare(strict_types=1);
namespace App\Services;
use App\Repositories\UserRepository;
class UserService
{
    private UserRepository $repository;
    public function __construct(UserRepository $repository)
    {
        $this->repository = $repository;
    }
    public function getUserList(): array
    {
        $users = $this->repository->findAll();
        // 注释风格:解释"为什么",而非"是什么"
        return array_map(function (array $user): array {
            return [
                'id' => (int) $user['id'],
                'user_name' => $user['user_name'],
            ];
        }, $users);
    }
}

版本控制(Git Flow)

1 分支模型

main        ├── 生产环境代码(受保护,不可直接推送)
hotfix/*    ├── 紧急修复(从 main 检出,修复后合并回 main 和 develop)
release/*   ├── 发布准备(从 develop 检出,合并回 main 和 develop)
develop     ├── 日常集成(受保护,不可直接推送)
feature/*   ├── 新功能开发(从 develop 检出,合并回 develop)
            └── 示例:feature/user-login

2 提交规范(Conventional Commits)

类型 说明 示例
feat 新功能 feat: add user registration endpoint
fix 修复 Bug fix: resolve null pointer exception in order module
docs 文档变更 docs: update README with API examples
style 格式调整 style: format code with php-cs-fixer
refactor 代码重构 refactor: extract payment logic to service class
test 测试相关 test: add unit tests for UserService
chore 构建/工具 chore: update composer dependencies
perf 性能优化 perf: add Redis cache for hot product queries
revert 回滚提交 revert: revert commit 2a3f4b5
格式:
<type>(<scope>): <subject>
示例:
feat(order): add order cancellation API
- 新增订单取消接口
- 增加取消原因记录
- 补充单元测试
Refs: #123

3 Code Review 流程

  • 所有代码合并到 develop 必须通过 Pull Request(或 Merge Request)
  • PR 至少 1-2 人 审查通过后方可合并
  • PR 需关联任务/缺陷编号
  • Review 重点:代码质量、逻辑正确性、安全漏洞、是否符合规范

环境与依赖管理

1 开发环境标准化

  • 使用 Docker 统一开发环境(统一 PHP 版本、扩展、服务版本)
  • 推荐使用 Laravel Sail 或 Docker Compose 搭建开发环境
  • PHP 版本、Composer 版本、扩展列表须在 README.md 中明确记录

2 Composer 依赖管理

  • 所有依赖必须通过 composer.json 管理
  • 生产依赖require)与 开发依赖require-dev)严格区分
  • 提交 composer.lock 到 Git 仓库,确保生产安装一致
  • 新增依赖须在 PR 中说明理由

测试规范

1 测试分层与覆盖目标

层级 技术要求 特点 覆盖目标
单元测试 PHPUnit 模拟外部依赖、不访问数据库 Service/Utility 类 ≥ 80%
集成测试 PHPUnit + TestCase 使用独立测试数据库 Repository/ORM 模型 ≥ 70%
接口测试 Pest 或 PHPUnit 模拟 HTTP 请求,使用独立测试数据库 Controller 核心接口 ≥ 90%
E2E 测试 Playwright(可选) 完整用户流程 核心业务链路 100%
静态分析 PHPStan / Psalm 不运行代码 严格级别 ≥ 6
代码风格 PHP-CS-Fixer 自动格式化 PSR-12 100%
安全审计 依赖漏洞扫描(如 composer audit 检查依赖安全 零高危漏洞

2 测试命名和结构

目录结构:
tests/
├── Unit/          # 单元测试
│   └── Services/
│       └── UserServiceTest.php
├── Integration/   # 集成测试
│   └── Repositories/
│       └── UserRepositoryTest.php
└── Feature/       # 接口测试(Laravel 惯例)
    └── UserApiTest.php

命名约定: 测试方法用下划线或小驼峰描述行为,推荐形式:

PHP项目团队协作规范

// 推荐行为驱动风格
public function test_user_can_register_with_valid_data(): void
{
    // Arrange(准备数据)
    // Act(执行操作)
    // Assert(断言结果)
}

3 覆盖率要求

  • 新代码行覆盖率 ≥ 80%
  • 关键业务逻辑(支付、权限、数据处理)覆盖率 ≥ 90%
  • 使用 phpunit --coverage-html ./coverage 生成报告

4 CI 自动化

  • 每次 PR 必须通过 CI 全部检查(GitHub Actions / GitLab CI 均可)
# .github/workflows/ci.yml 示例
name: CI
on: [push, pull_request]
jobs:
  php-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          coverage: xdebug
      - run: composer install --prefer-dist --no-interaction
      - run: cp .env.ci .env
      - run: php artisan key:generate
      - run: vendor/bin/phpunit
      - run: vendor/bin/phpstan analyse --memory-limit=512M
      - run: vendor/bin/php-cs-fixer fix --dry-run --diff

数据库规范

1 迁移(Migration)

  • 所有表结构变更必须通过迁移文件完成,禁止手动修改数据库
  • 迁移文件名清晰描述用途:2024_01_15_100000_add_status_to_orders_table.php
  • 每个迁移只做一件事
  • 生产环境数据变更(数据修复、大批量更新)用独立数据迁移(如 Laravel 的 db:seed 或专门的数据迁移类)

2 索引设计

// 推荐使用迁移内建方法管理索引
Schema::table('orders', function (Blueprint $table) {
    $table->index('user_id');                    // 查询频繁字段
    $table->unique('order_no');                  // 业务唯一字段
    $table->index(['status', 'created_at']);     // 复合索引
});

索引设计三个"必须":

  • 所有外键必须建立索引
  • 高频查询条件必须建立索引
  • 复合索引必须遵守最左前缀原则

3 软删除与审计字段

  • 核心业务表必须包含 created_atupdated_at 审计字段
  • 需要保留历史数据的表使用 deleted_at 软删除(Laravel 的 SoftDeletes trait)
  • 关键表可增加 created_byupdated_by 记录操作人

4 SQL 规范

  • 禁止在循环中执行 SQL(N+1 问题),使用 eager loading(with()
  • 复杂查询使用查询构造器或 ORM,禁止拼接原生 SQL
  • 大量数据操作用 chunk() 分批处理

安全规范

1 输入验证

  • 所有用户输入必须经过验证
  • 禁止直接拼接用户输入到 SQL 语句(使用预处理语句)
  • 文件上传严格校验类型、大小、内容

2 输出转义

  • 视图层输出使用模板引擎的自动转义(Blade 的 )
  • 禁止直接输出用户提交的 HTML 内容

3 认证与授权

  • 使用框架内置认证机制(Laravel Sanctum / JWT)
  • 接口必须实现权限控制(RBAC 或策略类)
  • 敏感操作记录操作日志

4 敏感数据保护

  • 密码使用 password_hash(),禁止明文或 MD5
  • .env 文件中的密钥严禁提交到 Git
  • API 密钥、数据库密码存于环境变量或密钥管理服务

日志与监控

1 日志规范

  • 使用统一日志格式(JSON 结构化推荐)
  • 日志级别使用规范:
    • debug:调试信息(仅开发环境)
    • info:常规操作记录
    • notice:正常但重要事件
    • warning:出现异常但未影响功能
    • error:需要关注的错误
    • critical:系统关键功能不可用
  • 关键业务操作必须记录日志(订单创建、支付回调、用户注册等)
// 推荐方式
Log::channel('daily')->info('Order created', [
    'order_id' => $order->id,
    'user_id' => $order->user_id,
    'amount' => $order->amount,
]);

2 错误监控

  • 部署 Sentry 或同类错误监控系统
  • 生产环境关闭 display_errors,记录日志而非输出

文档规范

1 README 必需内容

  • 项目简介与功能架构图
  • 环境要求(PHP 版本、扩展、服务)
  • 安装步骤(克隆、安装依赖、配置环境、初始化数据库)
  • 常用命令(启动、测试、代码格式化)
  • 目录结构说明
  • API 文档地址或说明

2 API 文档

  • 使用 OpenAPI(Swagger)Postman 维护 API 文档
  • 接口变更必须同步更新文档
  • 每个接口注明:请求方法、路径、参数、返回示例、错误码

3 代码内注释

  • 复杂类、方法必须写 PHPDoc
  • 注释说明意图而非机械重复代码
  • 使用 @param@return@throws 标注

部署流程

1 发布流程

feature/* → develop(开发集成) → release/*(发布准备) → main(生产)
                    ↓                    ↓
              (自动测试)        (灰度验证/手动测试)

2 部署清单

  • [ ] 单元/集成测试全部通过
  • [ ] PHPStan/Psalm 静态分析通过
  • [ ] 代码风格检查通过
  • [ ] 依赖安全检查通过
  • [ ] 迁移文件已生成并测试
  • [ ] 环境变量配置已更新
  • [ ] 文档已同步更新
  • [ ] 版本号已更新(遵循语义化版本)

3 发布要求

  • 每次发布必须打 Git Tag(如 v1.2.0
  • 紧急修复走 hotfix/* 分支,禁止直接在 main 修改
  • 数据库迁移在生产环境执行前必须在预发布环境演练

沟通与协作流程

1 每日站会

  • 每人汇报:昨日完成、今日计划、遇到的阻塞
  • 时间控制在 15 分钟内

2 代码评审

  • 提交 PR 时附上变更说明
  • 评审人在 24 小时内完成评审
  • 争议问题:在评审中解决,避免私下争论

3 任务管理

  • 使用 Jira / 禅道 / Trello 等项目管理工具
  • 任务状态:待处理 → 开发中 → 测试中 → 已完成
  • 每个任务关联代码提交记录

十一、常用工具配置

1 PHP-CS-Fixer 配置(.php-cs-fixer.php

<?php
return (new PhpCsFixer\Config())
    ->setRules([
        '@PSR-12' => true,
        'array_syntax' => ['syntax' => 'short'],
        'no_unused_imports' => true,
        'ordered_imports' => ['sort_algorithm' => 'alpha'],
        'single_quote' => true,
        'trailing_comma_in_multiline' => true,
    ])
    ->setFinder(
        PhpCsFixer\Finder::create()
            ->in(['app', 'routes', 'tests', 'database'])
    );

2 PHPStan 配置(phpstan.neon

parameters:
    level: 6
    paths:
        - app
        - tests
    tmpDir: storage/framework/cache/phpstan

3 自动化 Githook

# .git/hooks/pre-commit(示例)
#!/bin/sh
if [ -f "vendor/bin/php-cs-fixer" ]; then
    vendor/bin/php-cs-fixer fix --dry-run --diff src/
    if [ $? -ne 0 ]; then
        echo "❌ 代码风格检查未通过,请先运行 php-cs-fixer fix"
        exit 1
    fi
fi
if [ -f "vendor/bin/phpstan" ]; then
    vendor/bin/phpstan analyse
    if [ $? -ne 0 ]; then
        echo "❌ 静态分析未通过"
        exit 1
    fi
fi
exit 0

十二、常见痛点与解决方案

常见问题 解决方案
每个人的代码风格不统一 强制使用 PHP-CS-Fixer + pre-commit 钩子
数据库结构混乱 所有变更走迁移,禁止手动修改
测试环境不一致 使用 Docker 统一环境
合并冲突频繁 小步提交(每次功能独立分支)、频繁合并 develop
安全漏洞被忽视 定期 composer audit + 依赖自动更新检查
代码走查流于形式 走查清单化(安全、性能、可读性、测试)

快速参考命令

# 安装依赖
composer install
# 运行测试
vendor/bin/phpunit
# 静态分析
vendor/bin/phpstan analyse
# 代码格式化
vendor/bin/php-cs-fixer fix
# 创建迁移
php artisan make:migration create_users_table
# 执行迁移
php artisan migrate
# 代码检查(一键组合)
composer check-all

规范可根据团队实际技术栈(Laravel / Symfony / ThinkPHP 等)和项目规模进行调整,核心原则是:自动化、一致性、可追溯、持续改进,建议在项目启动时与全体成员一起讨论确认,形成团队共识后严格执行。

抱歉,评论功能暂时关闭!