// +---------------------------------------------------------------------- declare(strict_types=1); namespace ywxapp\controller; use think\App; /** * API 控制器基础类(App / 小程序 / 第三方客户端通用) * * 统一提供:JWT 登录态注入、未登录 401 拦截、标准响应封装。 * 业务控制器继承本类即可复用登录态(\ywxapp\model\MemberUser)与响应(\ywxapp\library\Result)。 * * 鉴权约定: * - 子类通过 $noNeedLogin 声明“免登录即可访问”的 action,['*'] 表示全部放行。 * - 其余 action 在构造阶段统一校验登录态,未登录直接返回 HTTP 401。 * - 统一响应:成功 $this->result->success($data),失败 $this->result->error($msg, $code)。 * * @package ywxapp\controller */ class ApiBase extends BaseController { /** * 无需登录即可访问的 action 列表,['*'] 表示全部放行。 * * @var array */ protected $noNeedLogin = []; /** * 无需额外校验的 action 列表(兼容旧写法,语义同 $noNeedLogin)。 * * @var array */ protected $noNeedVerify = []; /** * 构造方法。 * * 完成父类初始化后,依次调用 initialize()(子类自定义初始化)与 * checkLogin()(统一登录拦截)。 * * @param App $app 应用实例 */ public function __construct(App $app) { parent::__construct($app); $this->initialize(); $this->checkLogin(); } /** * 控制器初始化钩子,子类可重写以执行构造后的自定义初始化逻辑。 * * @return void */ protected function initialize() {} /** * 统一登录拦截。 * * 当当前 action 不在 $noNeedLogin / $noNeedVerify 白名单,且会员未登录时, * 直接返回 HTTP 401,阻止后续业务执行。 * * @return void */ protected function checkLogin(): void { $action = $this->request->action(); $white = array_merge($this->noNeedLogin, $this->noNeedVerify); if (in_array('*', $white, true) || in_array($action, $white, true)) { return; } if (!$this->auth || !$this->auth->isLogin) { $this->result->apiError('请先登录', 401, null, 401); } } /** * 获取当前登录会员模型(\ywxapp\model\MemberUser)。 * * 未登录访问已被 checkLogin() 拦截,此处仅作兜底返回。 * * @return \ywxapp\model\MemberUser 当前登录会员模型 */ protected function user() { if ($this->auth && $this->auth->isLogin) { return $this->auth->info; } $this->result->apiError('请先登录', 401, null, 401); } /** * 获取当前登录会员的主键 ID(uid)。 * * @return int 会员 uid,未登录时为 0 */ protected function uid(): int { return (int) ($this->auth->model->uid ?? 0); } /** * API 成功响应(强制 JSON,统一契约). * * 透传至 \ywxapp\library\Result::apiSuccess():固定 JSON、字段 * code/msg/data/timestamp,自动携带 token 与分页 count。 * * @param mixed $data 业务数据 * @param string $message 成功提示语 * @param int $count 分页总数(可选) * * @return void */ protected function apiSuccess($data = null, string $message = 'success', int $count = 0): void { $this->result->apiSuccess($data, $message, $count); } /** * API 失败响应(强制 JSON,业务 code 与 HTTP 状态解耦). * * 透传至 \ywxapp\library\Result::apiError():固定 JSON、字段 * code/msg/data/timestamp;业务 code 原样透传,HTTP 状态由 $httpStatus 控制。 * * @param string $message 失败提示语 * @param int $code 业务状态码(默认 1,鉴权失败建议 401) * @param mixed $data 附加数据(可选) * @param int $httpStatus HTTP 状态码(默认 200) * * @return void */ protected function apiError(string $message = 'Error', int $code = 1, $data = null, int $httpStatus = 200): void { $this->result->apiError($message, $code, $data, $httpStatus); } }