skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
youlaitech/youlai-skills108 installs

thinkphp

ThinkPHP backend development standards. Use this skill when developing ThinkPHP projects, implementing REST APIs, model data access, or JWT authentication.

How do I install this agent skill?

npx skills add https://github.com/youlaitech/youlai-skills --skill thinkphp
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    The skill provides comprehensive development standards and boilerplate code for ThinkPHP 8 projects, including RESTful API design, JWT authentication, and exception handling. No security issues were detected.

  • Socketpass

    No alerts

  • Snykpass

    Risk: LOW · No issues

What does this agent skill do?

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

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/youlaitech/youlai-skills/thinkphp">View thinkphp on skillZs</a>