app->request * - 子类在方法开头调用 setRequest($request),之后可用 $this->request 访问 */ abstract class BaseController { /** * 当前请求实例(由 setRequest($request) 设置,来源于方法参数 $request,非 think\App) * @var WebmanRequest|null */ protected ?WebmanRequest $request = null; /** * 是否批量验证 * @var bool */ protected bool $batchValidate = false; /** * 初始化 * @access protected */ protected function initialize(): void { } /** * 设置当前请求(子类方法开头调用) * @param WebmanRequest $request */ protected function setRequest(WebmanRequest $request): void { $this->request = $request; } /** * 操作成功(封装为返回 Response 的方法,替代原 $this->success() 抛异常) * @param string $msg 提示消息 * @param mixed $data 返回数据 * @param int $code 业务状态码(1=成功) * @param array $header 可含 statusCode 指定 HTTP 状态 */ protected function success(string $msg = '', mixed $data = null, int $code = 1, array $header = []): Response { return $this->result($msg, $data, $code, $header); } /** * 操作失败(封装为返回 Response 的方法,替代原 $this->error() 抛异常) * @param string $msg 提示消息 * @param mixed $data 返回数据 * @param int $code 业务状态码(0=失败) * @param array $header 可含 statusCode 指定 HTTP 状态(如 401、409) */ protected function error(string $msg = '', mixed $data = null, int $code = 0, array $header = []): Response { return $this->result($msg, $data, $code, $header); } /** * 返回 API 数据(BuildAdmin 格式:code, msg, time, data) * 使用 response() 生成 JSON Response */ protected function result(string $msg, mixed $data = null, int $code = 0, array $header = []): Response { if (trim($msg) === '') { $msg = $code === 1 ? __('Success') : __('Failed'); if (trim($msg) === '') { $msg = $code === 1 ? 'success' : 'failed'; } } $body = [ 'code' => $code, 'msg' => $msg, 'time' => time(), 'data' => $data, ]; $statusCode = $header['statusCode'] ?? 200; unset($header['statusCode']); if ($code !== 1) { $req = $this->request; $method = $req ? $req->method() : ''; $path = $req ? trim($req->path(), '/') : ''; $ip = $req ? strval($req->getRealIp()) : ''; $msgForLog = $msg; if (function_exists('mb_strlen') && function_exists('mb_substr') && mb_strlen($msgForLog) > 2000) { $msgForLog = mb_substr($msgForLog, 0, 2000) . '...'; } elseif (strlen($msgForLog) > 2000) { $msgForLog = substr($msgForLog, 0, 2000) . '...'; } Log::error('[API] ' . $method . ' /' . $path . ' | business_code=' . strval($code) . ' http=' . strval($statusCode) . ' ip=' . $ip . ' msg=' . $msgForLog); } $headers = array_merge(['Content-Type' => 'application/json'], $header); $options = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES; if (defined('JSON_INVALID_UTF8_SUBSTITUTE')) { $options |= JSON_INVALID_UTF8_SUBSTITUTE; } $jsonBody = json_encode($body, $options); if ($jsonBody === false) { $jsonBody = '{"code":0,"msg":"JSON encode error","time":' . time() . ',"data":[]}'; } return response($jsonBody, $statusCode, $headers); } }