一键导入
thinkphp
ThinkPHP backend development standards. Use this skill when developing ThinkPHP projects, implementing REST APIs, model data access, or JWT authentication.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
ThinkPHP backend development standards. Use this skill when developing ThinkPHP projects, implementing REST APIs, model data access, or JWT authentication.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Git version control automation standards. Use this skill when generating commit messages, managing version numbers, creating tags, or generating changelogs and release notes.
MySQL database design standards. Use this skill when designing table structures, field types, indexes, or naming conventions for MySQL databases.
Vue 3 + TypeScript development standards. Use this skill when building Vue 3 applications with Composition API, Pinia, UnoCSS and SCSS. Covers naming, CSS architecture, component structure, API patterns and code quality. UI-library agnostic (Element Plus, Ant Design Vue, etc).
ASP.NET Core backend development standards. Use this skill when developing ASP.NET Core projects, implementing REST APIs, using Entity Framework Core, or JWT authentication.
Django REST Framework backend development standards. Use this skill when developing Django projects, implementing REST APIs with DRF ViewSets, Serializers, or JWT authentication.
FastAPI 后端开发规范. Use this skill when developing FastAPI projects, implementing REST APIs with SQLAlchemy async, Pydantic v2 schemas, JWT/Redis token authentication, or the youlai-fastapi admin backend.
| name | thinkphp |
| description | ThinkPHP backend development standards. Use this skill when developing ThinkPHP projects, implementing REST APIs, model data access, or JWT authentication. |
| 层 | 选型 | 说明 |
|---|---|---|
| 运行环境 | PHP 8.1+ | 纤程、枚举、只读属性 |
| 框架 | ThinkPHP 8.x | MVC 架构、ORM 内置 |
| 数据库 | MySQL 8.x | InnoDB 引擎 |
| 缓存 | Redis 7.x | 分布式缓存 |
| 认证 | firebase/php-jwt | JWT 签发/验签 |
| API 文档 | Swagger UI (swagger.json) | 静态文档 |
基础目录以 ThinkPHP 8 官方目录结构 为准;
app/在此基础上按业务模块(auth、system等)划分,模块内含 controller/model/service/validate。
app/
├── BaseController.php # 基础控制器
├── ExceptionHandle.php # 全局异常处理
├── common.php, middleware.php # 公共函数 / 中间件定义
│
├── auth/ # 认证模块
│ ├── controller/{AuthController, WxMaAuthController}
│ └── service/{AuthService, WxMaAuthService}
│
├── system/ # 系统管理
│ ├── controller/{UserController, RoleController, MenuController, ...}
│ ├── model/{User, Role, Menu, ...}
│ ├── service/{UserService, RoleService, RolePermService, DataPermissionService, ...}
│ ├── validate/{UserValidate, RoleValidate}
│ └── enums/{ActionType, LogModule}
│
├── codegen/ # 代码生成器
├── file/ # 文件管理
│
├── common/ # 公共代码
│ ├── constants/ # RedisConstants, RedisKey
│ ├── enums/ # DataScopeEnum
│ ├── exception/ # BusinessException
│ ├── middleware/ # Auth, Perm, DataScope, Cors, Log, RateLimit, ConvertCase
│ ├── model/BaseModel.php
│ ├── traits/{AuthTrait, ParamsTrait}
│ ├── util/{CaseConverter, IdStringify, PageUtil, VerifyCodeHelper}
│ └── web/ # Result, PageResult, ResultCode, IResultCode
│
├── controller/BaseController.php # 基础控制器
│
extend/ # 扩展类库
├── jwt/{JwtTokenManager, TokenManager, ...}
├── redis/{RedisClient, KeyFormatter}
├── sse/{SseEmitter, SseService, ...}
└── http/HttpClient.php
config/ route/ public/ sql/
设计原则:
common/ 是公共组件,被所有模块共享extend/ 是第三方/框架扩展(JWT/Redis/SSE),不依赖业务app/{module}/ 按模块组织,每模块含 controller/model/service/validate遵循 ThinkPHP 8.0 开发规范 + PSR-4。
| 规则 | 示例 |
|---|---|
| 目录使用小写+下划线 | controller/, user_service/ |
| 类名采用驼峰法(首字母大写) | UserController, UserValidate |
| 类名与文件名一致 | UserController → UserController.php |
| 命名空间与目录路径一致 | app\system\controller → app/system/controller/ |
| 类型 | 规范 | 示例 |
|---|---|---|
| 常量 | 大写字母和下划线 | APP_PATH, HAS_ONE |
| 配置参数 | 小写字母和下划线 | url_route_on |
| 环境变量 | 大写字母和下划线 | APP_DEBUG, DB_HOST |
| 规则 | 示例 |
|---|---|
| 数据表使用小写+下划线 | sys_user, sys_role_menu |
| 字段使用小写+下划线 | user_name, create_time |
| 禁止驼峰和中文命名 | ❌ userName, ❌ 用户表 |
| 类型 | 规范 | 示例 |
|---|---|---|
| 方法 | 驼峰法(首字母小写) | getUserName() |
| 全局函数 | 小写字母和下划线 | get_client_ip() |
| 属性 | 驼峰法(首字母小写) | $tableName |
| 操作 | 方法 | 路径 |
|---|---|---|
| 分页列表 | GET | /api/v1/users/page |
| 详情 | GET | /api/v1/users/:id |
| 新增 | POST | /api/v1/users |
| 更新 | PUT | /api/v1/users |
| 删除 | DELETE | /api/v1/users/:id |
| 批量删除 | DELETE | /api/v1/users/batch |
| 下拉选项 | GET | /api/v1/users/options |
declare(strict_types=1);
namespace app\system\controller;
use app\BaseController;
use app\system\model\User;
use app\system\validate\UserValidate;
use app\common\exception\BusinessException;
use app\common\web\ResultCode;
final class UserController extends BaseController
{
protected bool $requireAuth = true;
/** 用户分页列表 */
public function page()
{
$params = $this->request->get();
$result = User::where(function ($q) use ($params) {
if (!empty($params['keywords']))
$q->whereLike('username|nickname', $params['keywords']);
if (isset($params['status']))
$q->where('status', $params['status']);
})->order('create_time', 'desc')
->paginate(['page' => $params['pageNum'] ?? 1, 'list_rows' => $params['pageSize'] ?? 20]);
return $this->successPaginate($result->items(), $result->total());
}
/** 新增用户 */
public function create()
{
$params = $this->request->post();
$this->validate($params, UserValidate::class, 'create');
if (User::where('username', $params['username'])->find())
throw new BusinessException(ResultCode::USER_ERROR, '用户名已存在');
$user = new User();
$user->username = $params['username'];
$user->password = password_hash($params['password'], PASSWORD_BCRYPT);
$user->save();
return $this->success(['id' => $user->id]);
}
}
class Result
{
public static function success(mixed $data = null, string $msg = '成功'): array
{
return ['code' => '00000', 'msg' => $msg, 'data' => $data];
}
public static function page(array $list, int $total): array
{
return ['code' => '00000', 'msg' => '成功', 'data' => ['list' => $list, 'total' => $total]];
}
public static function failedWith(ResultCode $code, string $msg = ''): array
{
return ['code' => $code->value, 'msg' => $msg ?: $code->getMsg(), 'data' => null];
}
}
abstract class BaseController
{
protected function success(mixed $data = null, string $msg = ''): Json
{
return json(Result::success($data, $msg ?: ResultCode::SUCCESS->getMsg()));
}
protected function successPaginate(array $list, int $total): Json
{
return json(Result::page($list, $total));
}
}
final class BusinessException extends RuntimeException
{
private ResultCode $resultCode;
public function __construct(ResultCode $resultCode, string $message = '')
{
$this->resultCode = $resultCode;
parent::__construct($message ?: $resultCode->getMsg());
}
public function getResultCode(): ResultCode { return $this->resultCode; }
}
class ExceptionHandle extends Handle
{
public function render($request, Throwable $e): Response
{
if ($e instanceof BusinessException)
return json(Result::failedWith($e->getResultCode(), $e->getMessage()));
if ($e instanceof ValidateException)
return json(Result::failedWith(ResultCode::PARAM_ERROR, $e->getError()));
return parent::render($request, $e); // 生产环境隐藏详情
}
}
// config/app.php — 注册异常处理器
return ['exception_handle' => \app\ExceptionHandle::class];
class BaseModel extends Model
{
protected $autoWriteTimestamp = true;
protected $createTime = 'create_time';
protected $updateTime = 'update_time';
use \think\model\concern\SoftDelete;
protected $deleteTime = 'delete_time';
protected $defaultSoftDelete = 0;
}
final class User extends BaseModel
{
protected $name = 'sys_user';
protected $pk = 'id';
protected $hidden = ['password', 'delete_time'];
public function dept()
{
return $this->belongsTo(Dept::class, 'dept_id');
}
public function roles()
{
return $this->belongsToMany(Role::class, UserRole::class, 'role_id', 'user_id');
}
}
use think\facade\Route;
// 认证接口(无需登录)
Route::group('api/v1/auth', function () {
Route::post('login', 'auth.controller.AuthController/login');
Route::post('logout', 'auth.controller.AuthController/logout');
Route::post('refresh-token', 'auth.controller.AuthController/refreshToken');
})->allowCrossDomain();
// 需要登录的接口
Route::group('api/v1', function () {
Route::group('users', function () {
Route::get('page', 'system.controller.UserController/page');
Route::get(':id', 'system.controller.UserController/detail');
Route::post('', 'system.controller.UserController/create');
Route::put('', 'system.controller.UserController/update');
Route::delete(':id', 'system.controller.UserController/delete');
Route::delete('batch', 'system.controller.UserController/batchDelete');
});
})->middleware(\app\middleware\Auth::class)->allowCrossDomain();
final class JwtService
{
public static function generateAccessToken(array $payload): string
{
$payload['exp'] = time() + Config::get('jwt.access_ttl', 7200);
$payload['iat'] = time();
$payload['iss'] = Config::get('jwt.issuer', 'youlai-think');
return JWT::encode($payload, Config::get('jwt.secret'), 'HS256');
}
public static function parseToken(string $token): ?array
{
try {
return (array) JWT::decode($token, new Key(Config::get('jwt.secret'), 'HS256'));
} catch (\Exception) { return null; }
}
}
final class Auth
{
public function handle(Request $request, Closure $next): Response
{
$token = str_replace('Bearer ', '', $request->header('Authorization', ''));
if (empty($token)) return json(Result::failedWith(ResultCode::ACCESS_TOKEN_INVALID));
$payload = JwtService::parseToken($token);
if (!$payload) return json(Result::failedWith(ResultCode::ACCESS_TOKEN_INVALID));
$request->userId = $payload['sub'];
$request->username = $payload['username'] ?? '';
return $next($request);
}
}
final class UserValidate extends Validate
{
protected $rule = [
'username' => 'require|max:50',
'password' => 'require|min:6|max:20',
'nickname' => 'require|max:50',
'mobile' => 'mobile',
'status' => 'in:0,1',
];
protected $scene = [
'create' => ['username', 'password', 'nickname', 'mobile', 'status'],
'update' => ['id', 'nickname', 'mobile', 'status'],
];
}
/** */ 注释@param/@return/@throwsdeclare(strict_types=1) 在文件首行(PHP 8 强制类型检查)/**
* 用户管理控制器。
*/
final class UserController extends BaseController
{
/**
* 创建新用户。
*
* @return Json {"code":"00000","data":{"id":1}}
* @throws BusinessException 用户名已存在
*/
public function create()
{
// ...
}
}
Result / ResultCode)ExceptionHandle)BusinessException + ResultCodeBaseModel,使用软删除UserValidate 验证器校验参数declare(strict_types=1) 在文件首行| 反模式 | 正确做法 |
|---|---|
return json(['code' => 0]) 散落各处 | 用 Result::success() 统一封装 |
| Controller 中直接 SQL 查询 | 委托 Model / Service 层 |
if (!$user) { exit('用户不存在'); } | 抛 BusinessException,走全局异常处理 |
catch (\Exception $e) { } 空捕获 | 记录日志或重新抛出 BusinessException |
| 表名使用驼峰 | sys_user(小写+下划线),禁止 SysUser |