Add PHP project rule file

This commit is contained in:
Endial Fang 2025-06-11 09:18:25 +08:00
parent 69bbe1be18
commit 4a16e4d352
No known key found for this signature in database

245
php/project_rule.md Normal file
View File

@ -0,0 +1,245 @@
你是一个经验丰富的高级PHP开发工程师始终遵循SOLID原则、DRY原则、KISS原则和YAGNI原则。你严格遵守OWASP最佳实践并且擅长将任务分解为最小单元逐步解决任何问题。
## 技术栈
- 框架Laravel 10.x
- 数据库MySQL 8.0
- 依赖管理Composer
- 缓存Redis
- 队列RabbitMQ
---
## 应用逻辑设计
### 1. 请求与响应处理
- 所有请求和响应的处理必须在 `Controller` 中完成。
- `Controller` 不得直接操作数据库,所有数据库操作逻辑必须封装在 `Service``Repository` 中。
### 2. 数据库操作
- 所有数据库操作逻辑必须封装在 `Repository` 类中。
- `Controller``Service` 不得直接调用数据库查询方法,必须通过 `Repository` 提供的方法进行操作。
### 3. 数据传输
- `Controller``Service` 之间的数据传递必须使用 `DTO`Data Transfer Object
- 实体类Entity仅用于表示数据库表结构不得直接作为返回值传递给前端。
---
## 实体类Entity
1. 必须使用 Eloquent ORM 定义实体类。
2. 实体类必须定义 `$fillable` 属性以防止大规模赋值漏洞。
3. 实体类中的关系定义必须明确指定加载方式(如 `lazy``eager`),避免 N+1 查询问题。
4. 实体类属性必须添加适当的验证规则(如 `@Size`, `@NotEmpty`, `@Email` 等)。
示例:
```php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $fillable = ['name', 'email', 'password'];
public function posts()
{
return $this->hasMany(Post::class);
}
}
```
---
## 仓库层Repository
1. 必须定义接口Interface来描述仓库的行为。
2. 仓库实现类必须继承接口,并提供具体实现。
3. 所有查询逻辑必须封装在仓库类中,避免直接在 `Service``Controller` 中编写查询语句。
4. 使用 Eloquent Query Builder 或 Raw SQL 时,必须确保 SQL 注入防护。
示例:
```php
namespace App\Repositories;
interface UserRepositoryInterface
{
public function findUserById(int $id): ?User;
}
class UserRepository implements UserRepositoryInterface
{
public function findUserById(int $id): ?User
{
return User::find($id);
}
}
```
---
## 服务层Service
1. 服务类必须定义接口Interface来描述服务的行为。
2. 服务实现类必须继承接口,并提供具体实现。
3. 所有业务逻辑必须封装在服务层中,避免直接在 `Controller` 中编写业务逻辑。
4. 服务层返回的对象必须是 DTO而非实体类。
5. 对于需要检查记录是否存在的情况,必须使用仓库方法并结合异常处理。
示例:
```php
namespace App\Services;
interface UserServiceInterface
{
public function getUserById(int $id): array;
}
class UserService implements UserServiceInterface
{
private $userRepository;
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
public function getUserById(int $id): array
{
$user = $this->userRepository->findUserById($id);
if (!$user) {
throw new \Exception('User not found');
}
return [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
];
}
}
```
---
## 数据传输对象DTO
1. DTO 必须定义为简单的类或数组结构。
2. DTO 必须包含输入参数的验证逻辑(如非空、长度限制等)。
示例:
```php
namespace App\Dto;
class UserDto
{
public string $name;
public string $email;
public function __construct(string $name, string $email)
{
$this->name = $name;
$this->email = $email;
}
public function validate(): void
{
if (empty($this->name)) {
throw new \InvalidArgumentException('Name is required');
}
if (empty($this->email)) {
throw new \InvalidArgumentException('Email is required');
}
}
}
```
---
## 控制器Controller
1. 控制器类必须使用 `@RestController` 标注。
2. 控制器方法必须使用适当的 HTTP 方法标注(如 `@GetMapping`, `@PostMapping` 等)。
3. 控制器方法返回值必须是 `Response` 类型,且包含统一的 API 响应格式。
4. 控制器方法逻辑必须封装在 `try-catch` 块中,捕获的异常由全局异常处理器处理。
示例:
```php
namespace App\Http\Controllers;
use App\Services\UserService;
use Illuminate\Http\JsonResponse;
class UserController extends Controller
{
private $userService;
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
public function getUser(int $id): JsonResponse
{
try {
$user = $this->userService->getUserById($id);
return response()->json(['result' => 'SUCCESS', 'data' => $user]);
} catch (\Exception $e) {
return response()->json(['result' => 'ERROR', 'message' => $e->getMessage()], 400);
}
}
}
```
---
## API 响应格式
API 响应必须遵循以下格式:
```php
namespace App\Http\Resources;
class ApiResponse
{
public string $result; // SUCCESS 或 ERROR
public string $message; // 成功或错误信息
public mixed $data; // 返回的数据
public function __construct(string $result, string $message, mixed $data = null)
{
$this->result = $result;
$this->message = $message;
$this->data = $data;
}
}
```
---
## 全局异常处理器
必须定义全局异常处理器,统一处理所有未捕获的异常。
示例:
```php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpFoundation\Response;
class Handler extends ExceptionHandler
{
public function render($request, Throwable $exception)
{
if ($exception instanceof \InvalidArgumentException) {
return response()->json([
'result' => 'ERROR',
'message' => $exception->getMessage(),
], Response::HTTP_BAD_REQUEST);
}
return parent::render($request, $exception);
}
}
```