hooker[$key]['func'] = $hooker; $this->hooker[$key]['args'] = $args; return $this; } /** * 设置where hooker * @param object $hooker * @return $this * @throws \Exception */ final public function setWhereHooker($hooker, $args = null) { $this->checkCallable($hooker); $this->setHooker('where', $hooker, $args); return $this; } /** * 获取where条件 * * @return array|mixed */ public function getWhereHooker() { $where = $this->properties(); if(isset($this->hooker['where']) && $this->hooker['where'] && is_callable($this->hooker['where']['func'])) { $where = call_user_func($this->hooker['where']['func'], $this->properties(), $this->hooker['where']['args']); } return $where; } /** * 设置order by hooker * @param object $hooker * @return $this * @throws \Exception */ final public function setOrderHooker($hooker, $args = null) { $this->checkCallable($hooker); $this->setHooker('order', $hooker, $args); return $this; } /** * 设置 limit hooker * * @param object $hooker * @return $this * @throws \Exception */ final public function setLimitHooker($hooker, $args = null) { $this->checkCallable($hooker); $this->setHooker('limit', $hooker, $args); return $this; } /** * 获取limit * @return int|mixed */ final public function getLimitHooker() { if(isset($this->hooker['limit']) && $this->hooker['limit'] && is_callable($this->hooker['limit']['func'])) { return call_user_func($this->hooker['limit']['func'], [], $this->hooker['limit']['args']); } return []; } /** * 设置 cache hooker * * @param callable $hooker * @param array| mixed $args * @return $this * @throws \Exception */ final public function setCacheHooker($hooker, $args = null) { $this->checkCallable($hooker); $this->setHooker('cache', $hooker, $args); return $this; } /** * 获取Cache Hooker * @return mixed|null[] */ final public function getCacheHooker() { if(isset($this->hooker['cache']) && $this->hooker['cache'] && is_callable($this->hooker['cache']['func'])) { return call_user_func($this->hooker['cache']['func'], [], $this->hooker['cache']['args']); } return [null, null, null]; } /** * 缓存设置 * * @param array $config 缓存配置 * @return void */ final public function setCacheConfig($config) { if(!is_array($config)) { return; } self::$config['cache'] = $config; } /** * 获取缓存的配置信息 * * @return array */ final public function getCacheConfig() { if(is_array(self::$config) && isset(self::$config['cache']) && is_array(self::$config['cache'])) { return self::$config['cache']; } return array(); } /** * 如果hooker不可调用即抛出异常 * * @param object $hooker * @return void * @throws \Exception */ private function checkCallable($hooker) { if($hooker && !is_callable($hooker)) { throw new \Exception('Hooker is uncallable'); } } /** * 设置order by hooker * @param object $hooker * @return $this * @throws \Exception */ final public function setQueryFieldsHooker($hooker, $args = null) { if(!is_callable($hooker)) { throw new \Exception('Hooker is un callable'); } $this->setHooker('fields', $hooker, $args); return $this; } /** * 通过field hooker返回查询的字段 * * @return mixed|string */ final public function getFieldsHooker() { if(isset($this->hooker['fields']) && $this->hooker['fields'] && is_callable($this->hooker['fields']['func'])) { return call_user_func($this->hooker['fields']['func'], [], $this->hooker['fields']['args']); } return '*'; } /** * 获取指定field的值 * @param string $field * @return mixed */ final public function getFieldVal($field) { if(!preg_match('/^[a-zA-Z]/', $field)) { throw new \Exception('Field is illegal'); } $property = $this->entity()->convertToProperty($field); return $this->{$property}; } /** * 返回使用的db信息 * * @return \Qii\Driver\Base */ final public function db() { return _loadClass('\Qii\Driver\Model'); } /** * 返回 entity 信息 * @return mixed */ final public function entity() { return _loadClass('\Qii\Driver\Entity\Entity'); } /** * unique (unique 如果是 array 则表示 联合唯一,如果是string则是任意唯一,多个单独唯一使用字符串以逗号隔开, 主键除外) * * @return mixed * @throws \Exception */ public function uniqueKey(){ throw new \Exception('请设置唯一值'); } /** * 主键 * * @return mixed * @throws \Exception */ public function primaryKey(){ throw new \Exception('请设置主键'); } /** * 保存数据的时候,验证唯一需要排除的值,此处仅支持,单个或联合排除,不支持单个排除 * * @return array */ public function exclude(){ return array(); } /** * order by * @return string[] */ public function orderBy() { return array(); } /** * explode string * @param string $separator 分隔符 * @param string $string 分割的字符串 * @param int $limit 是否 * @return array|false|string[] */ public function explode($separator, $string, $limit = PHP_INT_MAX) { if($string == '') { return []; } return explode($separator, $string, $limit); } /** * 添加数据验证字段 * * $fields = []; * return $this->valid($fields); * * @return mixed * @throws \Exception */ public function validFieldsForAdd(){ throw new \Exception('请设置插入数据验证的字段,格式如:["Id", "Title"],Id和Title为entity的属性'); } /** * 更新数据验证字段 * * $fields = []; * return $this->valid($fields); * * @return mixed * @throws \Exception */ public function validFieldsForUpdate() { throw new \Exception('请设置更新数据验证的字段,格式如:["Id", "Title"],Id和Title为entity的属性'); } /** * 获取不为空的属性 * * @return array */ final public function properties() { $class = get_called_class(); $method = new \ReflectionClass($class); $properties = $method->getproperties(); $fields = []; foreach($properties as $property) { if($property->isPublic()) { $name = $property->getName(); if(!isset($this->$name)) { continue; } $field = $this->entity()->convertToField($name); $fields[$field] = $this->$name; } } return $fields; } /** * 清除变量内容 * @return $this */ final public function clear() { $class = get_called_class(); $method = new \ReflectionClass($class); $properties = $method->getproperties(); $fields = []; foreach($properties as $property) { if($property->isPublic()) { $name = $property->getName(); if(!isset($this->$name)) { continue; } $this->$name = null; } } return $this; } /** * 获取默认值 * * @return array */ final public function getDefaultValue() { $default = []; $defaultValue = $this->defaultFieldsValue(); if(!$defaultValue || !is_array($defaultValue) || count($defaultValue) == 0) { return $default; } foreach ($defaultValue as $key => $value) { $field = $this->entity()->convertToField($key); $default[$field] = $value; } return $default; } /** * 获取总行数 * * @return mixed * @throws \Exception */ final public function count() { return $this->db()->fields(' COUNT(1) as count')->where($this->getWhereHooker())->selectOne($this->getTable()); } /** * 检查是否有对应的属性 * * @param $key * @return bool */ final public function hasProperty($key) { $class = get_called_class(); $key = $this->entity()->convertToProperty($key); if(isset(self::$properties[$class])) { return isset(self::$properties[$class][$key]); } $method = new \ReflectionClass($class); $properties = $method->getproperties(); $fields = array(); foreach($properties as $property) { if($property->isPublic()) { $name = $property->getName(); $fields[$name] = ''; } } self::$properties[$class] = $fields; return isset($fields[$key]); } /** * bind value * @param $values * @return $this */ final public function bindValues($values) { if(!is_array($values)) { return $this; } foreach ($values as $key => $value) { $property = $this->entity()->convertToProperty($key); if($this->hasProperty($key)) { $this->$property = $value; } } return $this; } /** * 获取数据 * * @return Object * @throws \Exception */ final public function get() { $class = get_called_class(); $obj = new $class(); $response = $this->info(); if($response->isError()) { return $obj; } $info = $response->getResult()['body']; if(!$info) { return $obj; } foreach ($info as $key => $val) { $key = $this->entity()->convertToProperty($key); $obj->$key = $val; } return $obj; } /** * 与get不同的这个返回的是Response * @return mixed|\Qii\Driver\Qii\Driver\Response */ final public function info() { try{ $info = $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->selectRow($this->getTable()); return Response::Success( static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '获取成功', 'body' => $info]] ); }catch (\Exception $e) { return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => $this->db()->getMessage(), 'body' => []] ]); } } /** * 是否相关数据存在 * * @return bool */ final public function exist() { $where = $this->getWhereHooker(); if(!$where) { return false; } return (bool) $this->db()->where($where)->selectOne($this->getTable()); } /** * 保存数据 * * @return mixed|Response * @throws \Exception */ final public function add() { $valid = $this->validFieldsForAdd(); if($valid->isError()) { return $valid; } //如果设置了 unique 就先验证唯一性 list($uniqueWhere, $exclude, $primary) = $this->condition(); unset($exclude); //如果 $where $or 为空,看看主键是否有设置值,有设置值说明验证主键就可以,反之设置了主键,主键值设置了,只验证主键就可以了 if(count($primary) > 0) { $exist = $this->db()->limit(1)->where($primary)->selectRow($this->getTable()); if($exist) { return Response::Exist(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DOES_EXIST, 'msg' => '数据已经存在', 'body' => $exist]] ); } } if(count($uniqueWhere) > 0) { $exist = $this->db()->limit(1)->where($uniqueWhere)->selectRow($this->getTable()); if($exist) { return Response::Exist(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DOES_EXIST, 'msg' => '数据已经存在', 'body' => $exist]] ); } } $values = array_merge($this->getDefaultValue(), $this->properties()); $res = $this->db()->insertObject($this->getTable(), $values); if($this->db()->isError()) { return Response::FailSave(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => $this->db()->getMessage(), 'body' => []] ]); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '添加成功', 'body' => $res]] ); } /** * 删除指定数据 * * @return false|Response */ public function remove() { if(!$this->properties()) { return Response::FailRemove(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => '未指定删除属性,不允许删除', 'body' => 0] ]); } $properties = []; foreach ($this->properties() as $key => $val) { $properties[] = $this->entity()->convertToProperty($key); } $valid = $this->valid($properties); if($valid->isError()) { return $valid; } $affectedRows = $this->db()->where($this->getWhereHooker())->delete($this->getTable()); if($this->db()->isError()) { return Response::FailRemove(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => $this->db()->getMessage(), 'body' => 0] ]); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '删除成功,总共删除了'. $affectedRows . '条记录', 'body' => $affectedRows]] ); } /** * 更新 * * @return mixed | Response * @throws \Exception */ final public function update(){ $valid = $this->validFieldsForUpdate(); if($valid->isError()) { return $valid; } //检查是否有重复的 list($uniqueWhere, $exclude, $primaryKey) = $this->condition(); // 检查 unique 是否已经存在相关数据 $diffWhere = array_diff_assoc($uniqueWhere, $primaryKey); if(count($diffWhere) > 0) { $unique = $this->db()->limit(1)->where($diffWhere)->exclude($exclude)->selectRow($this->getTable()); if($unique) { return Response::Exist(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DOES_EXIST, 'msg' => '已经存在相关记录', 'body' => $unique]] ); } } $where = []; $whereHooker = $this->getWhereHooker(); foreach ($whereHooker as $key => $val) { $keyArr = explode(':', $key); if(isset($primaryKey[$keyArr[0]])) { unset($primaryKey[$keyArr[0]]); $where[$key] = $val; } } if(count($where) > 0) { $primaryKey = $where; } //检查更新的数据是否存在,以主键为主 $exit = $this->db()->limit(1)->where($primaryKey)->selectOne($this->getTable()); if($exit === null || $exit === false) { return Response::NotExist(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DOES_NOT_EXIST, 'msg' => '未找到相关记录', 'body' => []]] ); } //获取默认值 //更新的时候不使用默认值 //$values = array_merge($this->getDefaultValue(), $this->properties()); $affectedRows = $this->db()->updateObject($this->getTable(), $this->properties(), $primaryKey); if($this->db()->isError()) { return Response::FailUpdate(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_UPDATE, 'msg' => $this->db()->getMessage(), 'body' => []]] ); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '数据更新成功', 'body' => $affectedRows]] ); } /** * 更新字段 * * @return mixed|Response * @throws \Exception */ final public function updateFields() { $properties = $this->properties(); $fields = $this->entity()->convertToProperties(array_keys($properties)); $valid = $this->valid($fields); if($valid->isError()) { return $valid; } list($uniqueWhere, $exclude, $primaryKey) = $this->condition(); // 检查 unique 是否已经存在相关数据 $diffWhere = array_diff_assoc($uniqueWhere, $primaryKey); if(count($diffWhere) > 0) { $unique = $this->db()->limit(1)->where($diffWhere)->exclude($exclude)->selectRow($this->getTable()); if($unique) { return Response::Exist(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DOES_EXIST, 'msg' => '已经存在相关记录', 'body' => $unique]] ); } } /*$whereHooker = $this->getWhereHooker(); if(!empty($whereHooker)) { $primaryKey = $whereHooker; }*/ $where = []; $whereHooker = $this->getWhereHooker(); foreach ($whereHooker as $key => $val) { $keyArr = explode(':', $key); if(isset($primaryKey[$keyArr[0]])) { unset($primaryKey[$keyArr[0]]); $where[$key] = $val; } } if(count($where) > 0) { $primaryKey = $where; } //检查更新的数据是否存在,以主键为主 $exit = $this->db()->limit(1)->where($primaryKey)->selectOne($this->getTable()); if($exit === null || $exit === false) { return Response::NotExist(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DOES_NOT_EXIST, 'msg' => '未找到相关记录', 'body' => []]] ); } //获取默认值 //更新的时候不使用默认值 //$values = array_merge($this->getDefaultValue(), $this->properties()); $affectedRows = $this->db()->updateObject($this->getTable(), $this->properties(), $primaryKey); if($this->db()->isError()) { return Response::FailUpdate(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_UPDATE, 'msg' => $this->db()->getMessage(), 'body' => []]] ); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '数据更新成功', 'body' => $affectedRows]] ); } /** * 增加或减少某一个字段的值 * * @return mixed|Response * @throws \Exception */ final public function incr() { list($where, $exclude, $primary) = $this->condition(); unset($where, $exclude); $property = $this->properties(); $incr = []; foreach ($property as $key => $value) { if(!is_numeric($value)) { continue; } $incr[$key] = $value; } $diff = array_diff_assoc($incr, $primary); if(count($diff) == 0) { return Response::Fail(self::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_FAIL, 'msg' => 'INCR 参数错误']]); } $sets = []; foreach ($diff as $key => $val) { if($val == 0) { $sets[$key] = $val; }else if($val > 0) { $sets[$key . ':plus'] = $val; }else if($val < 0) { $sets[$key . ':minus'] = $val * -1; } } $whereHooker = $this->getWhereHooker(); if(!empty($whereHooker)) { foreach ($whereHooker as $key => $where) { //去掉where条件里边的sets的值 $keys = $this->explode(":", $key); if(isset($diff[$keys[0]])) { unset($whereHooker[$key]); } } $primary = $whereHooker; } $affectedRows = $this->db()->set($sets)->where($primary)->update($this->getTable()); if($this->db()->isError()) { return Response::FailUpdate(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_UPDATE, 'msg' => $this->db()->getMessage(), 'body' => []]] ); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'INCR 成功', 'body' => $affectedRows]] ); } /** * 获取第一条数据 * * @return mixed|Response * @throws \Exception */ final public function first() { $orderBy = $this->getOrderBy(); //未设置order by 就以主键为准 if(empty($orderBy)) { $orderBy = $this->primaryCondition(); } foreach ($orderBy as $key => $value) { $orderBy[$key] = 'ASC'; } $row = $this->db()->orderBy($orderBy)->limit(1)->selectRow($this->getTable()); if($this->db()->isError()) { return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => 'Query 失败', 'body' => []]]); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'Query 成功', 'body' => $row]] ); } /** * 获取第一条数据 * * @return mixed|Response * @throws \Exception */ final public function last() { $orderBy = $this->getOrderBy(); //未设置order by 就以主键为准 if(empty($orderBy)) { $orderBy = $this->primaryCondition(); } foreach ($orderBy as $key => $value) { $orderBy[$key] = 'DESC'; } $row = $this->db()->fields($this->getFieldsHooker())->orderBy($orderBy)->limit(1)->selectRow($this->getTable()); if($this->db()->isError()) { return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => 'Query 失败', 'body' => []]]); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'Query 成功', 'body' => $row]] ); } /** * listts * @param int $page 页码 * @param int $pageSize 页大小 * @return array * @throws \Exception */ final public function lists($page = 1, $pageSize = 20) { $count = $this->count(); if(!$this->initPages($data, $count, $page, $pageSize)) { return $data; } $data['lists'] = $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->limit($data['pages']['limitStart'], $pageSize)->selectRows($this->getTable()); return $data; } /** * 获取所有数据,这里不分页,但支持限条数,通过 setLimitHooker来实现 * $this->setLimitHooker(function(){ * return [x,y];//从第x条开始获取y条; return [1];//获取一条 return [0];//获取所有的 * }); * @return mixed * @throws \Exception */ final public function listAll() { return $this->rsCondition()->selectRows($this->getTable()); } /** * 返回指针 * @return mixed * @throws \Exception */ final public function rs() { return $this->rsCondition()->rs($this->getTable()); } /** * 通过此方法获取 rs * @return mixed */ private function rsCondition() { $limit = $this->getLimitHooker(); if(empty($limit) || !is_array($limit)) { return $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy()); } if(count($limit) == 1) { return $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->limit($limit[0]); } return $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->limit($limit[0], $limit[1]); } /** * 验证相关字段 * * @param array $fields 字段列表 * @return Response */ final public function valid($fields = array()) { if(!is_array($fields)) { return Response::FailValidate(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_VALIDATE, 'msg' => '字段必须是数组', 'fields' => []]]); } $rules = $this->rules(); $result = []; $invalidKey = []; $values = array_merge($this->getDefaultValue(), $this->properties()); foreach ($rules as $valid => $rule) { foreach ($rule as $val) { $key = $this->entity()->convertToProperty($val[0]); if(!in_array($key, $fields)) { continue; } $field = $this->entity()->convertToField($key); $value = isset($values[$field]) ? $values[$field] : null; $limit = isset($val[2]) ? $val[2]: ''; $verify = new Verify($val[0], $value, strtolower($valid), $val[1], $limit); $res = $verify->valid(); if($res->isError()) { $result[] = $res->getResult() .',获取的是 '. $values[$field]; if(!in_array($field, $invalidKey)) { $invalidKey[] = $field; } } } } if(count($result) > 0) { return Response::FailValidate(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_VALIDATE, 'msg' => $result, 'fields' => $invalidKey]]); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => true]); } /** * 合并多个 valid 结果 $this->>valids($this->valid(['Uid']), $this->valid(['Nickname', 'Email'])); * @param ... * @return mixed|Response * @throws \Exception */ final public function valids() { $validArr = func_get_args(); if(count($validArr) == 0) { return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => true]); } if(count($validArr) == 1) { return $validArr[0]; } $invalid = array(); $invalid['message'] = array(); $invalid['fields'] = array(); foreach ($validArr as $valid) { if(!($valid instanceof Response)) { throw new \Exception('验证结果类型必须是\Qii\Drive\Response类型'); } if($valid->isError()) { $result = $valid->getResult(); $invalid['message'] = array_merge($invalid['message'], $result['message']); $invalid['fields'] = array_merge($invalid['fields'], $result['fields']);; } } if(count($invalid['message']) > 0) { return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['message' => $invalid['message'], 'fields' => $invalid['fields']]]); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => true]); } /** * unique 条件 * * @return array[] * @throws \Exception */ protected function uniqueCondition() { $uniqueWhere = []; $unique = $this->uniqueKey(); $useWhere = true; $condition = []; if(empty($unique)) { return $condition; } if(!is_array($unique)) { $unique = $this->explode(',', $unique); foreach ($unique as $val) { $condition[] = $val; } }else{ //检查是否是一维数组,一维数组联合唯一 if(count($unique) == count($unique, 1)) { $condition[] = $unique; }else{ $condition = $unique; } } foreach ($condition as $item) { $uniqueWhere[] = "OR"; $arr = []; foreach ($item as $key) { $key = $this->entity()->convertToField($key); $property = $this->entity()->convertToProperty($key); $arr[$key] = $this->$property; } $uniqueWhere[] = $arr; } return $uniqueWhere; } /** * exclude Condition * * @return array */ protected function excludeCondition() { if(is_array($this->exclude())) { $exclude = $this->exclude(); }else{ $exclude = (array) $this->explode(',', $this->exclude()); } $excludeCondition = []; foreach ($exclude as $key) { $field = $this->entity()->convertToField($key); $property = $this->entity()->convertToProperty($key); $excludeCondition[$field] = $this->$property; } return $excludeCondition; } /** * 主键 * * @return array * @throws \Exception */ protected function primaryCondition(){ $primary = array(); $primaryKey = $this->primaryKey(); if(!is_array($primaryKey)) { $primaryKey = $this->explode(',', $primaryKey); } foreach ($primaryKey as $key) { $key = $this->entity()->convertToProperty($key); $field = $this->entity()->convertToField($key); $value = $this->$key; $primary[$field] = $value; } return $primary; } /** * 获取查询条件 * * @return array [$uniqueWhere, $uniqueOr, $excludeCondition, $primaryCondition] */ final public function condition() { //如果设置了 unique 就先验证唯一性,保存的时候验证 uniqueKey,更新的时候验证uniqueKey并排primaryKey //保存数据的时候验证uniqueKey;更新时验证 uniqueKey,并且排除 primaryKey,如果uniqueKey == primaryKey则不去做唯一性验证 $uniqueWhere = $this->uniqueCondition(); $excludeCondition = $this->excludeCondition(); $primaryCondition = $this->primaryCondition(); return [$uniqueWhere, $excludeCondition, $primaryCondition]; } /** * 获取order by * * @return array */ final public function getOrderBy() { $order = array(); $orderBy = (array) $this->orderBy(); if(isset($this->hooker['order']) && is_callable($this->hooker['order']['func'])) { $orderBy = (array) call_user_func($this->hooker['order']['func'], $order, $this->hooker['order']['args']); } foreach ($orderBy as $key => $val) { $field = $this->entity()->convertToField($key); $val = strtoupper($val); if(!in_array($val, array('DESC', 'ASC'))) { continue; } $order[$field] = $val; } return (array) $order; } /** * 初始化page * @param array $data 返回的数据 * @param int $count 总数量 * @param int $page 页码 * @param int $pageSize 显示数量 * @param int $pagination 分页显示最多页码 * @return bool */ public function initPages(&$data, $count, $page, $pageSize = 20, $pagination = 5) { $page = max(1, $page); $pageSize = max(1, $pageSize); $data['start'] = 0; $data['pages'] = array('total' => 0, 'currentPage' => 0, 'totalPage' => 0); $data['pages']['total'] = (int) ($count ? $count : 0); $data['pages']['currentPage'] = $page; $data['pages']['totalPage'] = ceil($data['pages']['total'] / $pageSize); $data['lists'] = array(); if ($data['pages']['currentPage'] > $data['pages']['totalPage']) { return false; } $frames = array( 'left' => 0, 'right' => 0 ); $pagination = $pagination < $data['pages']['totalPage'] ? $pagination : $data['pages']['totalPage']; if($data['pages']['currentPage'] - floor($pagination / 2) <= 0) { $frames['left'] = 1; $frames['right'] = $frames['left'] + $pagination - 1; } else if($data['pages']['currentPage'] + floor($pagination / 2) >= $data['pages']['totalPage']) { $frames['right'] = $data['pages']['totalPage']; $frames['left'] = $frames['right'] - $pagination + 1; } else { $frames['left'] = $data['pages']['currentPage'] - floor($pagination / 2); $frames['right'] = $data['pages']['currentPage'] + ceil($pagination / 2) - 1; } $data['start'] = $frames['left']; $data['pages']['start'] = $data['start']; $data['pages']['end'] = $frames['right']; $data['pages']['pagination'] = $pagination; $data['pages']['limitStart'] = (min($page, $data['pages']['totalPage']) - 1) * $pageSize; $data['pages']['pageSize'] = (int) $pageSize; return true; } /** * response as object * * @return mixed|\Qii\Driver\Qii\Driver\Response */ final public function response() { $properties = $this->properties(); if(!$properties) { return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => '未找到相关数据', 'body' => []] ] ); } return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '获取成功', 'body' => $properties]] ); } /** * 方法名 + ByCache/ByRedis/ByMemcache/会将结果缓存,这里使用的缓存类是通过hooker设置的,否则使用对应的 * ByClean 则会移除当前缓存, 默认转发到 db model上 * @param string $method method * @param array $args * @return mixed */ public function __call($method, $args) { $cache = ''; preg_match("/(byredis|bymemcache|bycache|byclean)$/i", $method, $matches); if($matches && count($matches) > 0) { $cache = strtolower($matches[0]); } if($cache && in_array($cache, ['bymemcache', 'byredis', 'bycache', 'byclean'])){ list($func, $cacheID, $config) = $this->getCacheHooker(); $policy = $this->getCacheConfig(); if($func == null) { $func = $cache == 'bymemcache' ? $this->db()->setCache('memcached', $policy) : $this->db()->setCache('redis', $policy); } $method = substr($method, 0, strlen($cache) * -1); if (method_exists($this, $method)) { $key = get_called_class() .':'. $method .':'. substr(md5(serialize($this->properties())), -16); if($cache == 'byclean') { return $func->del($key); } if(is_object($func) && method_exists($func, 'get')) { $res = $func->get($key); if ($res) { return unserialize($res); } } $expiredAt = isset($config['life_time']) ? (int) $config['life_time'] : (isset($policy['life_time']) ? $policy['life_time'] : $this->defaultExpired); $res = call_user_func_array(array($this, $method), $args); $str = serialize($res); $func->set($key, $str, ['life_time' => $expiredAt]); return $res; } } return call_user_func_array(array($this->db(), $method), $args); } }