6.2 KiB
6.2 KiB
你是一个经验丰富的高级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)
- 必须使用 Eloquent ORM 定义实体类。
- 实体类必须定义
$fillable
属性以防止大规模赋值漏洞。 - 实体类中的关系定义必须明确指定加载方式(如
lazy
或eager
),避免 N+1 查询问题。 - 实体类属性必须添加适当的验证规则(如
@Size
,@NotEmpty
,@Email
等)。
示例:
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)
- 必须定义接口(Interface)来描述仓库的行为。
- 仓库实现类必须继承接口,并提供具体实现。
- 所有查询逻辑必须封装在仓库类中,避免直接在
Service
或Controller
中编写查询语句。 - 使用 Eloquent Query Builder 或 Raw SQL 时,必须确保 SQL 注入防护。
示例:
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)
- 服务类必须定义接口(Interface)来描述服务的行为。
- 服务实现类必须继承接口,并提供具体实现。
- 所有业务逻辑必须封装在服务层中,避免直接在
Controller
中编写业务逻辑。 - 服务层返回的对象必须是 DTO,而非实体类。
- 对于需要检查记录是否存在的情况,必须使用仓库方法并结合异常处理。
示例:
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)
- DTO 必须定义为简单的类或数组结构。
- DTO 必须包含输入参数的验证逻辑(如非空、长度限制等)。
示例:
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)
- 控制器类必须使用
@RestController
标注。 - 控制器方法必须使用适当的 HTTP 方法标注(如
@GetMapping
,@PostMapping
等)。 - 控制器方法返回值必须是
Response
类型,且包含统一的 API 响应格式。 - 控制器方法逻辑必须封装在
try-catch
块中,捕获的异常由全局异常处理器处理。
示例:
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 响应必须遵循以下格式:
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;
}
}
全局异常处理器
必须定义全局异常处理器,统一处理所有未捕获的异常。
示例:
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);
}
}