mcpField
T
thinkphp

thinkphp

github.com/youlaitechDevelopment62122 installsUpdated 4d ago
Repository

About thinkphp

A ThinkPHP 8.x backend development guide for PHP developers building REST APIs and modular applications. It defines project structure and conventions alongside patterns for responses, validation, authentication, and error handling.

Key features

  1. 01ThinkPHP 8.x project structure
  2. 02PSR-4 naming conventions
  3. 03RESTful API route patterns
  4. 04Unified response and exception handling
  5. 05JWT authentication conventions
  6. 06Validation and model guidelines

Use cases

  1. 01Set conventions for a ThinkPHP project
  2. 02Structure modular backend code
  3. 03Implement REST API endpoints
  4. 04Plan JWT authentication and validation

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/youlaitech/youlai-skills --skill thinkphp

After installing, type/thinkphpin Claude Code to confirm it loaded.

Details

From the project README

ThinkPHP 后端开发规范

参考:ThinkPHP 8.0 开发规范 | PSR-4 自动加载

触发条件

  • Develop ThinkPHP projects
  • Implement REST APIs
  • Use model data access
  • Implement JWT authentication
  • Implement permission control

Part 1: 技术栈

层选型说明
运行环境PHP 8.1+纤程、枚举、只读属性
框架ThinkPHP 8.xMVC 架构、ORM 内置
数据库MySQL 8.xInnoDB 引擎
缓存Redis 7.x分布式缓存
认证firebase/php-jwtJWT 签发/验签
API 文档Swagger UI (swagger.json)静态文档

Part 2: 目录结构

基础目录以 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

Part 3: 命名规范

遵循 ThinkPHP 8.0 开发规范 + PSR-4。

3.1 文件和类
规则示例
目录使用小写+下划线controller/, user_service/
类名采用驼峰法(首字母大写)UserController, UserValidate
类名与文件名一致UserController → UserController.php
命名空间与目录路径一致app\system\controller → app/system/controller/
3.2 常量和配置
类型规范示例
常量大写字母和下划线APP_PATH, HAS_ONE
配置参数小写字母和下划线url_route_on
环境变量大写字母和下划线APP_DEBUG, DB_HOST
3.3 数据表和字段
规则示例
数据表使用小写+下划线sys_user, sys_role_menu
字段使用小写+下划线user_name, create_time
禁止驼峰和中文命名❌ userName, ❌ 用户表
3.4 函数和变量
类型规范示例
方法驼峰法(首字母小写)getUserName()
全局函数小写字母和下划线get_client_ip()
属性驼峰法(首字母小写)$tableName

Part 4: RESTful API 规范

4.1 标准 CRUD 路径
操作方法路径
分页列表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
4.2 Controller 模板
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]);
    }
}

Part 5: 响应格式与异常处理

5.1 统一响应
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];
    }
}
5.2 基础控制器响应方法
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));
    }
}
5.3 业务异常
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; }
}
5.4 全局异常处理
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];

Part 6: 模型规范

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');
    }
}

Part 7: 路由规范

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();

Part 8: 认证规范

8.1 JWT 服务
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; }
    }
}
8.2 认证中间件
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);
    }
}

Part 9: 验证器规范

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'],
    ];
}

Part 10: 注释规范

  • 所有公共方法用 PHPDoc /** */ 注释
  • 方法注释含 @param/@return/@throws
  • declare(strict_types=1) 在文件首行(PHP 8 强制类型检查)
/**
 * 用户管理控制器。
 */
final class UserController extends BaseController
{
    /**
     * 创建新用户。
     *
     * @return Json {"code":"00000","data":{"id":1}}
     * @throws BusinessException 用户名已存在
     */
    public function create()
    {
        // ...
    }
}

Part 11: 代码质量检查清单

  • 目录使用小写+下划线,类名驼峰法
  • 数据表和字段使用小写+下划线
  • 遵循 RESTful API 路径规范
  • 使用统一响应格式(Result / ResultCode)
  • 实现全局异常处理(ExceptionHandle)
  • 业务异常使用 BusinessException + ResultCode
  • 模型继承 BaseModel,使用软删除
  • 使用 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

Comments

Markdown supported