PHP 可维护代码编写指南
遵循编码标准
<?php
// ❌ 不规范的代码
function getdata($id){return DB::table('users')->where('id',$id)->first();}
// ✅ 遵循 PSR-12 标准
function getData(int $id): ?User
{
return User::find($id);
}
建议采用的标准:

- PSR-12(代码风格)
- PSR-4(自动加载)
- PSR-1(基础编码标准)
使用类型提示
<?php
// ❌ 无类型提示
function calculate($a, $b) {
return $a * $b;
}
// ✅ 强类型提示
function calculate(float $a, float $b): float
{
return $a * $b;
}
// 标量类型声明
declare(strict_types=1);
单一职责原则
<?php
// ❌ 违反单一职责
class UserService {
public function register($data) {
// 验证
// 创建用户
// 发送邮件
// 记录日志
// 生成报告
}
}
// ✅ 职责分离
class UserRegistrationService {
public function register(UserData $data): User
{
// 只负责用户注册
}
}
class EmailService {
public function sendWelcomeEmail(User $user): void
{
// 只负责发送邮件
}
}
使用依赖注入
<?php
// ❌ 硬编码依赖
class OrderService {
private $db;
public function __construct() {
$this->db = new Database('localhost', 'user', 'pass');
}
}
// ✅ 依赖注入
class OrderService {
private $db;
private $logger;
public function __construct(DatabaseInterface $db, LoggerInterface $logger) {
$this->db = $db;
$this->logger = $logger;
}
}
善用设计模式
<?php
// 工厂模式
interface PaymentGateway {
public function pay(float $amount): bool;
}
class StripeGateway implements PaymentGateway {
public function pay(float $amount): bool
{
// Stripe 实现
}
}
class PayPalGateway implements PaymentGateway {
public function pay(float $amount): bool
{
// PayPal 实现
}
}
class PaymentFactory {
public static function create(string $type): PaymentGateway
{
switch ($type) {
case 'stripe':
return new StripeGateway();
case 'paypal':
return new PayPalGateway();
default:
throw new InvalidArgumentException("Unsupported payment method");
}
}
}
编写文档和注释
<?php
/**
* 计算订单总价
*
* @param array $items 订单商品列表
* @param float $taxRate 税率
* @param float $discount 折扣金额
*
* @return float 最终价格
* @throws InvalidArgumentException 当商品列表为空时
*/
function calculateOrderTotal(array $items, float $taxRate = 0.1, float $discount = 0): float
{
if (empty($items)) {
throw new InvalidArgumentException('Order items cannot be empty');
}
$subtotal = array_sum(array_column($items, 'price'));
$total = $subtotal * (1 + $taxRate) - $discount;
return max(0, $total);
}
使用命名空间和自动加载
<?php
// composer.json 配置
{
"autoload": {
"psr-4": {
"App\\": "src/",
"App\\Tests\\": "tests/"
}
}
}
// 使用命名空间
namespace App\Services;
use App\Repositories\UserRepository;
class UserService {
// ...
}
错误处理和日志记录
<?php
// ✅ 正确的错误处理
try {
$user = $this->userRepository->find($id);
if (!$user) {
throw new UserNotFoundException("User not found");
}
} catch (UserNotFoundException $e) {
$this->logger->error('User not found', ['id' => $id]);
throw new BusinessException('Invalid user');
} catch (Exception $e) {
$this->logger->critical('Unexpected error', [
'exception' => $e,
'user_id' => $id
]);
throw $e;
}
编写测试
<?php
use PHPUnit\Framework\TestCase;
class UserServiceTest extends TestCase {
public function testCreateValidUser(): void
{
$userData = new UserData('John', 'Doe', 'john@example.com');
$userService = new UserService();
$user = $userService->create($userData);
$this->assertInstanceOf(User::class, $user);
$this->assertEquals('John', $user->getFirstName());
$this->assertEquals('john@example.com', $user->getEmail());
}
}
代码审查清单
可维护性检查项:
- [ ] 变量命名清晰有意义
- [ ] 函数和方法简短(不超过20行)
- [ ] 类遵循单一职责
- [ ] 无重复代码(DRY原则)
- [ ] 使用PHP内置函数而非自定义
- [ ] 正确处理异常和错误
- [ ] 有清晰的注释和文档
- [ ] 遵循项目编码标准
- [ ] 使用类型提示和返回类型
- [ ] 无魔法数字和字符串
工具推荐
# 代码质量工具 composer require --dev phpstan/phpstan composer require --dev squizlabs/php_codesniffer composer require --dev phpunit/phpunit composer require --dev friendsofphp/php-cs-fixer # 运行检查 vendor/bin/phpstan analyse src vendor/bin/phpcs --standard=PSR12 src/ vendor/bin/php-cs-fixer fix src/
实际示例:一个完整的可维护服务
<?php
declare(strict_types=1);
namespace App\Services;
use App\Repositories\Interfaces\UserRepositoryInterface;
use App\Exceptions\UserValidationException;
use Psr\Log\LoggerInterface;
final class UserService
{
public function __construct(
private readonly UserRepositoryInterface $repository,
private readonly LoggerInterface $logger,
private readonly array $config
) {}
/**
* 创建新用户
*
* @param array $userData 用户数据
* @return User 创建的用户对象
* @throws UserValidationException 验证失败时抛出
*/
public function createUser(array $userData): User
{
try {
// 验证数据
$this->validateUserData($userData);
// 检查邮箱是否已存在
if ($this->repository->findByEmail($userData['email'])) {
throw new UserValidationException('Email already exists');
}
// 创建用户
$user = $this->repository->create([
'name' => $userData['name'],
'email' => $userData['email'],
'password' => $this->hashPassword($userData['password'])
]);
// 记录成功
$this->logger->info('User created successfully', [
'user_id' => $user->getId(),
'email' => $user->getEmail()
]);
return $user;
} catch (UserValidationException $e) {
$this->logger->warning('User creation failed', [
'error' => $e->getMessage(),
'data' => $userData
]);
throw $e;
}
}
private function validateUserData(array $data): void
{
// 验证逻辑
}
private function hashPassword(string $password): string
{
return password_hash($password, PASSWORD_DEFAULT);
}
}
最佳实践总结
- 命名要清晰 - 使用有意义的名称
- 函数要小 - 单一职责,便于测试
- 避免静态方法 - 优先使用依赖注入
- 使用异常而非错误码 - 更好的错误处理
- 缓存查询结果 - 提高性能
- 使用接口 - 解耦实现
- 避免全局状态 - 减少副作用
- 持续重构 - 保持代码简洁
通过这些实践,你可以编写出易于维护、测试和扩展的PHP代码,可维护性不是一次性的目标,而是持续的改进过程。