* @version : HUOSDK 8.0 */ namespace api\common\controller; use think\Db; use think\exception\HttpResponseException; use think\exception\HuoException; use think\exception\ValidateException; use think\Lang; use think\Loader; use think\Request; use think\Response; class ApiBaseController { //token protected $token = ''; //设备类型 protected $device_type = ''; //用户 id protected $mem_id = 0; // 语言 protected $lang = 'en'; //用户 protected $user; /* 返回类型 */ protected $response_type = 'json'; //用户类型 protected $user_type; protected $allowed_device_types = ['mobile', 'android', 'iphone', 'ipad', 'web', 'pc', 'mac', 'wxapp']; /** * @var \think\Request Request实例 */ protected $request; // 验证失败是否抛出异常 protected $fail_exception = false; // 是否批量验证 protected $batch_validate = false; /** * 前置操作方法列表 * * @var array $before_action_list * @access protected */ protected $before_action_list = []; /** * 架构函数 * * @param Request $request Request对象 * * @access public */ public function __construct(Request $request = null) { if (is_null($request)) { $request = Request::instance(); } // Request::instance()->root(cmf_get_root() . '/'); Lang::setAllowLangList(['en', 'ar']); $this->request = $request; // $this->response_type = Config::get('default_return_type'); $this->_initLang(); // 用户验证初始化 $this->_initUser(); // 控制器初始化 $this->_initialize(); // 前置操作方法 if ($this->before_action_list) { foreach ($this->before_action_list as $method => $options) { if (is_numeric($method)) { $this->beforeAction($options); } else { $this->beforeAction($method, $options); } } } } // 初始化 protected function _initialize() { } private function _initLang() { $_lang = $this->request->header('HS-Lang/s', 'en-us'); $this->lang = $_lang; config('default_lang', $this->lang); } private function _initUser() { $_token = $this->request->header('HS-Token/s', ''); $_device_type = $this->request->header('HS-Device-Type/s', ''); if (empty($_token)) { return; } if (empty($_device_type)) { return; } if (!in_array($_device_type, $this->allowed_device_types)) { return; } $this->token = $_token; $this->device_type = $_device_type; $_mem_id = $this->getMemIdByToken($_token, $_device_type); if (!empty($_mem_id)) { $this->mem_id = $_mem_id; } } /** * @param $token * @param $device_type * * @return array|bool|false|\PDOStatement|string|\think\Model */ public function getMemIdByToken($token, $device_type) { if (empty($token) || empty($device_type)) { return 0; } $_mem_id = Db::name('mem_token') ->where(['token' => $this->token, 'device_type' => $this->device_type]) ->value('mem_id'); if (empty($_mem_id)) { return 0; } return $_mem_id; } /** * 前置操作 * * @access protected * * @param string $method 前置操作方法名 * @param array $options 调用参数 ['only'=>[...]] 或者['except'=>[...]] */ protected function beforeAction($method, $options = []) { if (isset($options['only'])) { if (is_string($options['only'])) { $options['only'] = explode(',', $options['only']); } if (!in_array($this->request->action(), $options['only'])) { return; } } elseif (isset($options['except'])) { if (is_string($options['except'])) { $options['except'] = explode(',', $options['except']); } if (in_array($this->request->action(), $options['except'])) { return; } } call_user_func([$this, $method]); } /** * 设置验证失败后是否抛出异常 * * @access protected * * @param bool $fail 是否抛出异常 * * @return $this */ protected function validateFailException($fail = true) { $this->fail_exception = $fail; return $this; } /** * 验证数据 * * @access protected * * @param array $data 数据 * @param string|array $validate 验证器名或者验证规则数组 * @param array $message 提示信息 * @param bool $batch 是否批量验证 * @param mixed $callback 回调方法(闭包) * * @return array|string|true * @throws ValidateException */ protected function validate($data, $validate, $message = [], $batch = false, $callback = null) { if (is_array($validate)) { $_valid_class = Loader::validate(); $_valid_class->rule($validate); } else { if (strpos($validate, '.')) { // 支持场景 list($validate, $scene) = explode('.', $validate); } $_valid_class = Loader::validate($validate); if (!empty($scene)) { $_valid_class->scene($scene); } } // 是否批量验证 if ($batch || $this->batch_validate) { $_valid_class->batch(true); } if (is_array($message)) { $_valid_class->message($message); } if ($callback && is_callable($callback)) { call_user_func_array($callback, [$_valid_class, &$data]); } if (!$_valid_class->check($data)) { if ($this->fail_exception) { throw new ValidateException($_valid_class->getError()); } else { return $_valid_class->getError(); } } else { return true; } } /** * 操作成功跳转的快捷方法 * * @access protected * * @param mixed $msg 提示信息 * @param mixed $data 返回的数据 * @param array $header 发送的Header信息 * * @param int $code 返回码 * * @return void */ protected function success($msg = '', $data = '', $code = 200, array $header = []) { if (empty($data)) { $data = null; } $result = [ 'code' => $code, 'msg' => $msg, 'data' => $data, ]; $type = $this->getResponseType(); $header['Access-Control-Allow-Origin'] = '*'; $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,HS-Device-Type,HS-Token,HS-Lang'; $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS'; $response = Response::create($result, $type)->header($header); throw new HttpResponseException($response); } /** * 操作错误跳转的快捷方法 * * @access protected * * @param mixed $msg 提示信息,若要指定错误码,可以传数组,格式为['code'=>您的错误码,'msg'=>'您的错误消息'] * @param mixed $data 返回的数据 * @param array $header 发送的Header信息 * * @param int $code * * @return void */ protected function error($msg = '', $data = '', $code = 400, array $header = []) { if (empty($data)) { $data = null; } $result = [ 'code' => $code, 'msg' => $msg, 'data' => $data, ]; $type = $this->getResponseType(); $header['Access-Control-Allow-Origin'] = '*'; $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,HS-Device-Type,HS-Token,HS-Lang'; $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS'; $response = Response::create($result, $type)->header($header); throw new HttpResponseException($response); } /** * 获取当前的response 输出类型 * * @access protected * @return string */ protected function getResponseType() { return $this->response_type; } /** * 获取当前登录用户的id * * @return int */ public function getMemId() { if (empty($this->mem_id)) { // $this->error(lang('NO_LOGIN'), '', 1002); } $this->mem_id = rand(1, 10); return $this->mem_id; } }