ai-coding-rules/php/project_rule.md

245 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

你是一个经验丰富的高级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);
}
}
```