|
@@ -1,7 +1,9 @@
|
|
|
<?php
|
|
|
namespace Qii\Driver\Entity;
|
|
|
|
|
|
-use \Qii\Driver\Response;
|
|
|
+
|
|
|
+
|
|
|
+use Qii\Driver\Response;
|
|
|
|
|
|
class Base {
|
|
|
/**
|
|
@@ -12,7 +14,7 @@ class Base {
|
|
|
public static $properties;
|
|
|
public static $config;
|
|
|
/**
|
|
|
- * hooker for fields 查询字段/ where 查询条件 / order 排序 / cache 缓存
|
|
|
+ * hooker for fields 查询字段/ where 查询条件 / order 排序 / cache 缓存 / with 关联查询
|
|
|
* @var array $hooker
|
|
|
*/
|
|
|
private $hooker = [];
|
|
@@ -31,9 +33,7 @@ class Base {
|
|
|
*
|
|
|
* @return array
|
|
|
*/
|
|
|
- public function defaultFieldsValue(){
|
|
|
- return array();
|
|
|
- }
|
|
|
+ public function defaultFieldsValue(){}
|
|
|
|
|
|
/**
|
|
|
* 返回 table 的名字,以便分库分表的时候指定使用
|
|
@@ -44,31 +44,27 @@ class Base {
|
|
|
public function getTable() {
|
|
|
throw new \Exception('请先设置需要保存的数据表');
|
|
|
}
|
|
|
-
|
|
|
/**
|
|
|
* set hooker for method
|
|
|
* 目前 where 和 order 及 fields 支持
|
|
|
* @param $key
|
|
|
* @param $hooker
|
|
|
- * @param $args
|
|
|
- * @return $this
|
|
|
+ * @return void
|
|
|
*/
|
|
|
protected function setHooker($key, $hooker, $args) {
|
|
|
$this->hooker[$key]['func'] = $hooker;
|
|
|
$this->hooker[$key]['args'] = $args;
|
|
|
- return $this;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 设置where hooker
|
|
|
* @param object $hooker
|
|
|
- * @return $this
|
|
|
+ * @return void
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function setWhereHooker($hooker, $args = null) {
|
|
|
+ public function setWhereHooker($hooker, $args = null) {
|
|
|
$this->checkCallable($hooker);
|
|
|
$this->setHooker('where', $hooker, $args);
|
|
|
- return $this;
|
|
|
}
|
|
|
/**
|
|
|
* 获取where条件
|
|
@@ -77,7 +73,7 @@ class Base {
|
|
|
*/
|
|
|
public function getWhereHooker() {
|
|
|
$where = $this->properties();
|
|
|
- if(isset($this->hooker['where']) && $this->hooker['where'] && is_callable($this->hooker['where']['func'])) {
|
|
|
+ if(isset($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;
|
|
@@ -86,33 +82,31 @@ class Base {
|
|
|
/**
|
|
|
* 设置order by hooker
|
|
|
* @param object $hooker
|
|
|
- * @return $this
|
|
|
+ * @return void
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function setOrderHooker($hooker, $args = null) {
|
|
|
+ public function setOrderHooker($hooker, $args = null) {
|
|
|
$this->checkCallable($hooker);
|
|
|
$this->setHooker('order', $hooker, $args);
|
|
|
- return $this;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 设置 limit hooker
|
|
|
*
|
|
|
* @param object $hooker
|
|
|
- * @return $this
|
|
|
+ * @return void
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function setLimitHooker($hooker, $args = null) {
|
|
|
+ public function setLimitHooker($hooker, $args = null) {
|
|
|
$this->checkCallable($hooker);
|
|
|
- $this->setHooker('limit', $hooker, $args);
|
|
|
- return $this;
|
|
|
+ $this->setHooker('order', $hooker, $args);
|
|
|
}
|
|
|
/**
|
|
|
* 获取limit
|
|
|
* @return int|mixed
|
|
|
*/
|
|
|
- final public function getLimitHooker() {
|
|
|
- if(isset($this->hooker['limit']) && $this->hooker['limit'] && is_callable($this->hooker['limit']['func'])) {
|
|
|
+ public function getLimitHooker() {
|
|
|
+ if(isset($this->hooker['limit']) && is_callable($this->hooker['limit']['func'])) {
|
|
|
return call_user_func($this->hooker['limit']['func'], [], $this->hooker['limit']['args']);
|
|
|
}
|
|
|
return [];
|
|
@@ -123,21 +117,20 @@ class Base {
|
|
|
*
|
|
|
* @param callable $hooker
|
|
|
* @param array| mixed $args
|
|
|
- * @return $this
|
|
|
+ * @return void
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function setCacheHooker($hooker, $args = null) {
|
|
|
+ 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'])) {
|
|
|
+ public function getCacheHooker() {
|
|
|
+ if(isset($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];
|
|
@@ -149,7 +142,7 @@ class Base {
|
|
|
* @param array $config 缓存配置
|
|
|
* @return void
|
|
|
*/
|
|
|
- final public function setCacheConfig($config) {
|
|
|
+ public function setCacheConfig($config) {
|
|
|
if(!is_array($config)) {
|
|
|
return;
|
|
|
}
|
|
@@ -161,12 +154,46 @@ class Base {
|
|
|
*
|
|
|
* @return array
|
|
|
*/
|
|
|
- final public function getCacheConfig() {
|
|
|
+ public function getCacheConfig() {
|
|
|
if(is_array(self::$config) && isset(self::$config['cache']) && is_array(self::$config['cache'])) {
|
|
|
return self::$config['cache'];
|
|
|
}
|
|
|
return array();
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置关联子查询
|
|
|
+ *
|
|
|
+ * @param $hooker
|
|
|
+ * @params $args
|
|
|
+ * @return $this
|
|
|
+ * @throws \Exception
|
|
|
+ */
|
|
|
+ public function setWith($hooker, $args = null){
|
|
|
+ $this->checkCallable($hooker);
|
|
|
+ if(!isset($this->hooker['with'])) {
|
|
|
+ $this->hooker['with'] = [];
|
|
|
+ }
|
|
|
+ $this->hooker['with'][] = ['func' => $hooker, 'args' => $args];
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取with hooker
|
|
|
+ *
|
|
|
+ * @return mixed|null[]
|
|
|
+ */
|
|
|
+ public function getWithHooker() {
|
|
|
+ $callback = [];
|
|
|
+ if(isset($this->hooker['with'])) {
|
|
|
+ foreach ($this->hooker['with'] AS $hooker) {
|
|
|
+ if(is_callable($hooker['func'])) {
|
|
|
+ $callback[] = call_user_func($hooker['func'], [], $hooker['args']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $callback;
|
|
|
+ }
|
|
|
/**
|
|
|
* 如果hooker不可调用即抛出异常
|
|
|
*
|
|
@@ -182,15 +209,14 @@ class Base {
|
|
|
/**
|
|
|
* 设置order by hooker
|
|
|
* @param object $hooker
|
|
|
- * @return $this
|
|
|
+ * @return void
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function setQueryFieldsHooker($hooker, $args = null) {
|
|
|
+ public function setQueryFieldsHooker($hooker, $args = null) {
|
|
|
if(!is_callable($hooker)) {
|
|
|
throw new \Exception('Hooker is un callable');
|
|
|
}
|
|
|
$this->setHooker('fields', $hooker, $args);
|
|
|
- return $this;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -198,8 +224,8 @@ class Base {
|
|
|
*
|
|
|
* @return mixed|string
|
|
|
*/
|
|
|
- final public function getFieldsHooker() {
|
|
|
- if(isset($this->hooker['fields']) && $this->hooker['fields'] && is_callable($this->hooker['fields']['func'])) {
|
|
|
+ public function getFieldsHooker() {
|
|
|
+ if(isset($this->hooker['fields']) && is_callable($this->hooker['fields']['func'])) {
|
|
|
return call_user_func($this->hooker['fields']['func'], [], $this->hooker['fields']['args']);
|
|
|
}
|
|
|
return '*';
|
|
@@ -210,7 +236,7 @@ class Base {
|
|
|
* @param string $field
|
|
|
* @return mixed
|
|
|
*/
|
|
|
- final public function getFieldVal($field) {
|
|
|
+ public function getFieldVal($field) {
|
|
|
if(!preg_match('/^[a-zA-Z]/', $field)) {
|
|
|
throw new \Exception('Field is illegal');
|
|
|
}
|
|
@@ -222,7 +248,7 @@ class Base {
|
|
|
*
|
|
|
* @return \Qii\Driver\Base
|
|
|
*/
|
|
|
- final public function db() {
|
|
|
+ public function db() {
|
|
|
return _loadClass('\Qii\Driver\Model');
|
|
|
}
|
|
|
|
|
@@ -230,7 +256,7 @@ class Base {
|
|
|
* 返回 entity 信息
|
|
|
* @return mixed
|
|
|
*/
|
|
|
- final public function entity() {
|
|
|
+ public function entity() {
|
|
|
return _loadClass('\Qii\Driver\Entity\Entity');
|
|
|
}
|
|
|
|
|
@@ -316,7 +342,7 @@ class Base {
|
|
|
*
|
|
|
* @return array
|
|
|
*/
|
|
|
- final public function properties() {
|
|
|
+ public function properties() {
|
|
|
$class = get_called_class();
|
|
|
$method = new \ReflectionClass($class);
|
|
|
$properties = $method->getproperties();
|
|
@@ -334,33 +360,12 @@ class Base {
|
|
|
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() {
|
|
|
+ public function getDefaultValue() {
|
|
|
$default = [];
|
|
|
$defaultValue = $this->defaultFieldsValue();
|
|
|
if(!$defaultValue || !is_array($defaultValue) || count($defaultValue) == 0) {
|
|
@@ -379,7 +384,7 @@ class Base {
|
|
|
* @return mixed
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function count() {
|
|
|
+ public function count() {
|
|
|
return $this->db()->fields(' COUNT(1) as count')->where($this->getWhereHooker())->selectOne($this->getTable());
|
|
|
}
|
|
|
|
|
@@ -388,8 +393,9 @@ class Base {
|
|
|
*
|
|
|
* @param $key
|
|
|
* @return bool
|
|
|
+ * @throws \ReflectionException
|
|
|
*/
|
|
|
- final public function hasProperty($key) {
|
|
|
+ public function hasProperty($key) {
|
|
|
$class = get_called_class();
|
|
|
$key = $this->entity()->convertToProperty($key);
|
|
|
if(isset(self::$properties[$class])) {
|
|
@@ -412,8 +418,9 @@ class Base {
|
|
|
* bind value
|
|
|
* @param $values
|
|
|
* @return $this
|
|
|
+ * @throws \ReflectionException
|
|
|
*/
|
|
|
- final public function bindValues($values) {
|
|
|
+ public function bindValues($values) {
|
|
|
if(!is_array($values)) {
|
|
|
return $this;
|
|
|
}
|
|
@@ -431,7 +438,7 @@ class Base {
|
|
|
* @return Object
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function get() {
|
|
|
+ public function get() {
|
|
|
$class = get_called_class();
|
|
|
$obj = new $class();
|
|
|
$response = $this->info();
|
|
@@ -453,11 +460,14 @@ class Base {
|
|
|
* 与get不同的这个返回的是Response
|
|
|
* @return mixed|\Qii\Driver\Qii\Driver\Response
|
|
|
*/
|
|
|
- final public function info() {
|
|
|
+ public function info() {
|
|
|
try{
|
|
|
$info = $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->selectRow($this->getTable());
|
|
|
- return Response::Success(
|
|
|
- static::class .'::'. __FUNCTION__,
|
|
|
+
|
|
|
+ if($info) {
|
|
|
+ $this->withRow($info);
|
|
|
+ }
|
|
|
+ return Response::Success(static::class .'::'. __FUNCTION__,
|
|
|
['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '获取成功', 'body' => $info]]
|
|
|
);
|
|
|
}catch (\Exception $e) {
|
|
@@ -471,7 +481,7 @@ class Base {
|
|
|
*
|
|
|
* @return bool
|
|
|
*/
|
|
|
- final public function exist() {
|
|
|
+ public function exist() {
|
|
|
$where = $this->getWhereHooker();
|
|
|
if(!$where) {
|
|
|
return false;
|
|
@@ -481,16 +491,16 @@ class Base {
|
|
|
/**
|
|
|
* 保存数据
|
|
|
*
|
|
|
- * @return mixed|Response
|
|
|
+ * @return mixed|Qii\Driver\Response
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function add() {
|
|
|
+ public function add() {
|
|
|
$valid = $this->validFieldsForAdd();
|
|
|
if($valid->isError()) {
|
|
|
return $valid;
|
|
|
}
|
|
|
//如果设置了 unique 就先验证唯一性
|
|
|
- list($uniqueWhere, $exclude, $primary) = $this->condition();
|
|
|
+ list($uniqueWhere, $uniqueOr, $exclude, $primary) = $this->condition();
|
|
|
unset($exclude);
|
|
|
|
|
|
//如果 $where $or 为空,看看主键是否有设置值,有设置值说明验证主键就可以,反之设置了主键,主键值设置了,只验证主键就可以了
|
|
@@ -503,8 +513,8 @@ class Base {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(count($uniqueWhere) > 0) {
|
|
|
- $exist = $this->db()->limit(1)->where($uniqueWhere)->selectRow($this->getTable());
|
|
|
+ if(count($uniqueWhere) > 0 || count($uniqueOr) > 0) {
|
|
|
+ $exist = $this->db()->limit(1)->where($uniqueWhere)->orTerms($uniqueOr)->selectRow($this->getTable());
|
|
|
if($exist) {
|
|
|
return Response::Exist(static::class .'::'. __FUNCTION__,
|
|
|
['_result' => ['code' => Response::DOES_EXIST, 'msg' => '数据已经存在', 'body' => $exist]]
|
|
@@ -532,9 +542,7 @@ class Base {
|
|
|
*/
|
|
|
public function remove() {
|
|
|
if(!$this->properties()) {
|
|
|
- return Response::FailRemove(static::class .'::'. __FUNCTION__,
|
|
|
- ['_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => '未指定删除属性,不允许删除', 'body' => 0]
|
|
|
- ]);
|
|
|
+ return false;
|
|
|
}
|
|
|
$properties = [];
|
|
|
foreach ($this->properties() as $key => $val) {
|
|
@@ -547,8 +555,8 @@ class Base {
|
|
|
}
|
|
|
$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::FailSave(static::class .'::'. __FUNCTION__,
|
|
|
+ ['_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => $this->db()->getMessage(), 'body' => []]
|
|
|
]);
|
|
|
}
|
|
|
return Response::Success(static::class .'::'. __FUNCTION__,
|
|
@@ -558,38 +566,46 @@ class Base {
|
|
|
/**
|
|
|
* 更新
|
|
|
*
|
|
|
- * @return mixed | Response
|
|
|
+ * @return mixed | Qii\Driver\Response
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function update(){
|
|
|
+ public function update(){
|
|
|
$valid = $this->validFieldsForUpdate();
|
|
|
if($valid->isError()) {
|
|
|
return $valid;
|
|
|
}
|
|
|
//检查是否有重复的
|
|
|
- list($uniqueWhere, $exclude, $primaryKey) = $this->condition();
|
|
|
+ list($uniqueWhere, $uniqueOr, $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());
|
|
|
+ $diffOr = array_diff_assoc($uniqueOr, $primaryKey);
|
|
|
+ /*print_r(
|
|
|
+ [
|
|
|
+ 'where' => $uniqueWhere,
|
|
|
+ 'or' => $uniqueOr,
|
|
|
+ 'exclude' => $exclude,
|
|
|
+ 'primary' => $primaryKey
|
|
|
+ ]
|
|
|
+ );*/
|
|
|
+ /*$diffExclude = array_diff_assoc($exclude, $primaryKey);
|
|
|
+
|
|
|
+ print_r(
|
|
|
+ [
|
|
|
+ 'diffWhere' => $diffWhere,
|
|
|
+ 'diffOr' => $diffOr,
|
|
|
+ 'diffExclude' => $diffExclude
|
|
|
+ ]
|
|
|
+ );*/
|
|
|
+
|
|
|
+ if(count($diffWhere) > 0 || count($diffOr) > 0) {
|
|
|
+ $unique = $this->db()->limit(1)->where($diffWhere)->orTerms($diffOr)->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) {
|
|
@@ -615,46 +631,46 @@ class Base {
|
|
|
/**
|
|
|
* 更新字段
|
|
|
*
|
|
|
- * @return mixed|Response
|
|
|
+ * @return mixed|\Qii\Driver\Qii\Driver\Response|Response
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function updateFields() {
|
|
|
+ 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();
|
|
|
+ list($uniqueWhere, $uniqueOr, $exclude, $primaryKey) = $this->condition();
|
|
|
+ /*print_r(
|
|
|
+ [
|
|
|
+ 'where' => $uniqueWhere,
|
|
|
+ 'or' => $uniqueOr,
|
|
|
+ 'exclude' => $exclude,
|
|
|
+ 'primary' => $primaryKey
|
|
|
+ ]
|
|
|
+ );*/
|
|
|
// 检查 unique 是否已经存在相关数据
|
|
|
$diffWhere = array_diff_assoc($uniqueWhere, $primaryKey);
|
|
|
+ $diffOr = array_diff_assoc($uniqueOr, $primaryKey);
|
|
|
+ /*$diffExclude = array_diff_assoc($exclude, $primaryKey);
|
|
|
|
|
|
- if(count($diffWhere) > 0) {
|
|
|
- $unique = $this->db()->limit(1)->where($diffWhere)->exclude($exclude)->selectRow($this->getTable());
|
|
|
+ print_r(
|
|
|
+ [
|
|
|
+ 'diffWhere' => $diffWhere,
|
|
|
+ 'diffOr' => $diffOr,
|
|
|
+ 'diffExclude' => $diffExclude
|
|
|
+ ]
|
|
|
+ );*/
|
|
|
+
|
|
|
+ if(count($diffWhere) > 0 || count($diffOr) > 0) {
|
|
|
+ $unique = $this->db()->limit(1)->where($diffWhere)->orTerms($diffOr)->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) {
|
|
@@ -681,12 +697,12 @@ class Base {
|
|
|
/**
|
|
|
* 增加或减少某一个字段的值
|
|
|
*
|
|
|
- * @return mixed|Response
|
|
|
+ * @return mixed|Qii\Driver\Response
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function incr() {
|
|
|
- list($where, $exclude, $primary) = $this->condition();
|
|
|
- unset($where, $exclude);
|
|
|
+ public function incr() {
|
|
|
+ list($where, $or, $exclude, $primary) = $this->condition();
|
|
|
+ unset($where, $or, $exclude);
|
|
|
$property = $this->properties();
|
|
|
$incr = [];
|
|
|
foreach ($property as $key => $value) {
|
|
@@ -709,17 +725,6 @@ class Base {
|
|
|
$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()) {
|
|
@@ -735,15 +740,11 @@ class Base {
|
|
|
/**
|
|
|
* 获取第一条数据
|
|
|
*
|
|
|
- * @return mixed|Response
|
|
|
+ * @return mixed|\Qii\Driver\Response
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function first() {
|
|
|
+ public function first() {
|
|
|
$orderBy = $this->getOrderBy();
|
|
|
- //未设置order by 就以主键为准
|
|
|
- if(empty($orderBy)) {
|
|
|
- $orderBy = $this->primaryCondition();
|
|
|
- }
|
|
|
foreach ($orderBy as $key => $value) {
|
|
|
$orderBy[$key] = 'ASC';
|
|
|
}
|
|
@@ -751,6 +752,9 @@ class Base {
|
|
|
if($this->db()->isError()) {
|
|
|
return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => 'Query 失败', 'body' => []]]);
|
|
|
}
|
|
|
+ if($row) {
|
|
|
+ $this->withRow($row);
|
|
|
+ }
|
|
|
return Response::Success(static::class .'::'. __FUNCTION__,
|
|
|
['_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'Query 成功', 'body' => $row]]
|
|
|
);
|
|
@@ -758,15 +762,11 @@ class Base {
|
|
|
/**
|
|
|
* 获取第一条数据
|
|
|
*
|
|
|
- * @return mixed|Response
|
|
|
+ * @return mixed|\Qii\Driver\Response
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function last() {
|
|
|
+ public function last() {
|
|
|
$orderBy = $this->getOrderBy();
|
|
|
- //未设置order by 就以主键为准
|
|
|
- if(empty($orderBy)) {
|
|
|
- $orderBy = $this->primaryCondition();
|
|
|
- }
|
|
|
foreach ($orderBy as $key => $value) {
|
|
|
$orderBy[$key] = 'DESC';
|
|
|
}
|
|
@@ -774,10 +774,48 @@ class Base {
|
|
|
if($this->db()->isError()) {
|
|
|
return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => 'Query 失败', 'body' => []]]);
|
|
|
}
|
|
|
+ if($row) {
|
|
|
+ $this->withRow($row);
|
|
|
+ }
|
|
|
return Response::Success(static::class .'::'. __FUNCTION__,
|
|
|
['_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'Query 成功', 'body' => $row]]
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 附带一行数据
|
|
|
+ *
|
|
|
+ * @param $row
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function withRow(&$row) {
|
|
|
+ if(!is_array($row)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $hooks = $this->getWithHooker();
|
|
|
+ foreach ($hooks as $with) {
|
|
|
+ if(!is_array($with) || count($with) != 5 || !is_object($with[0])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $callable = $with[0];
|
|
|
+ $relField = $with[1];
|
|
|
+ $method = $with[2];
|
|
|
+ $foreignKey = $with[3];
|
|
|
+ $associationForeignkey = $with[4];
|
|
|
+ $row[$relField] = [];
|
|
|
+ if(!isset($row[$foreignKey])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $params = [$associationForeignkey,
|
|
|
+ [$associationForeignkey => $row[$foreignKey]]
|
|
|
+ ];
|
|
|
+ $res = call_user_func_array(array($callable, $method), $params);
|
|
|
+
|
|
|
+ if($res && isset($res[$row[$foreignKey]])) {
|
|
|
+ $row[$relField] = $res[$row[$foreignKey]];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
/**
|
|
|
* listts
|
|
|
* @param int $page 页码
|
|
@@ -785,48 +823,107 @@ class Base {
|
|
|
* @return array
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function lists($page = 1, $pageSize = 20) {
|
|
|
+ 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());
|
|
|
+ $lists = $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->limit($data['pages']['limitStart'], $pageSize)->selectRows($this->getTable());
|
|
|
+ $this->withList($lists);
|
|
|
+ $data['lists'] = $lists;
|
|
|
return $data;
|
|
|
}
|
|
|
+ /**
|
|
|
+ * 附带一行数据
|
|
|
+ *
|
|
|
+ * @param array $lists
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function withList(&$lists) {
|
|
|
+ if(!is_array($lists)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $hooks = $this->getWithHooker();
|
|
|
+ foreach ($hooks as $with) {
|
|
|
+ if(count($with) > 0 && is_object($with[0])) {
|
|
|
+ $callable = $with[0];
|
|
|
+ $relField = $with[1];
|
|
|
+ $method = $with[2];
|
|
|
+ $foreignKey = $with[3];
|
|
|
+ $associationForeignkey = $with[4];
|
|
|
|
|
|
+ $rel = [];
|
|
|
+ foreach ($lists as $v) {
|
|
|
+ if(isset($v[$foreignKey])) {
|
|
|
+ $rel[] = $v[$foreignKey];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // [rel key, where]
|
|
|
+ $params = [$associationForeignkey,
|
|
|
+ [$associationForeignkey . ':in' => array_unique($rel)]
|
|
|
+ ];
|
|
|
+ $res = call_user_func_array(array($with[0], $with[2]), $params);
|
|
|
+ foreach ($lists as &$v) {
|
|
|
+ if(isset($res[$v[$foreignKey]])) {
|
|
|
+ $v[$relField] = $res[$v[$foreignKey]];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
/**
|
|
|
- * 获取所有数据,这里不分页,但支持限条数,通过 setLimitHooker来实现
|
|
|
- * $this->setLimitHooker(function(){
|
|
|
- * return [x,y];//从第x条开始获取y条; return [1];//获取一条 return [0];//获取所有的
|
|
|
- * });
|
|
|
- * @return mixed
|
|
|
+ * 关联查询 has one
|
|
|
+ * params[rel_key, where]
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function listAll() {
|
|
|
- return $this->rsCondition()->selectRows($this->getTable());
|
|
|
+ public function hasOne() {
|
|
|
+ $args = func_get_args();
|
|
|
+ $relKey = $args[0];
|
|
|
+ $res = $this->db()->where($args[1])->rs($this->getTable());
|
|
|
+ $rows = [];
|
|
|
+ foreach($res as $k => $v) {
|
|
|
+ $rows[$v[$relKey]] = $v;
|
|
|
+ }
|
|
|
+ return $rows;
|
|
|
}
|
|
|
+
|
|
|
/**
|
|
|
- * 返回指针
|
|
|
- * @return mixed
|
|
|
+ * 关联查询
|
|
|
+ * params[rel_key, where]
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function rs() {
|
|
|
- return $this->rsCondition()->rs($this->getTable());
|
|
|
+ public function hasMany()
|
|
|
+ {
|
|
|
+ $args = func_get_args();
|
|
|
+ $relKey = $args[0];
|
|
|
+ $res = $this->db()->where($args[1])->rs($this->getTable());
|
|
|
+ $rows = [];
|
|
|
+ foreach($res as $k => $v) {
|
|
|
+ $rows[$v[$relKey]][] = $v;
|
|
|
+ }
|
|
|
+ return $rows;
|
|
|
}
|
|
|
-
|
|
|
/**
|
|
|
- * 通过此方法获取 rs
|
|
|
+ * 获取所有数据,这里不分页,但支持限条数,通过 setLimitHooker来实现
|
|
|
+ * $this->setLimitHooker(function(){
|
|
|
+ * return [x,y];//从第x条开始获取y条; return [1];//获取一条 return [0];//获取所有的
|
|
|
+ * });
|
|
|
* @return mixed
|
|
|
+ * @throws \Exception
|
|
|
*/
|
|
|
- private function rsCondition() {
|
|
|
+ public function listAll() {
|
|
|
$limit = $this->getLimitHooker();
|
|
|
if(empty($limit) || !is_array($limit)) {
|
|
|
- return $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy());
|
|
|
+ return $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->selectRows($this->getTable());
|
|
|
}
|
|
|
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])->selectRows($this->getTable());
|
|
|
}
|
|
|
- return $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->limit($limit[0], $limit[1]);
|
|
|
+ return $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->limit($limit[0], $limit[1])->selectRows($this->getTable());
|
|
|
}
|
|
|
/**
|
|
|
* 验证相关字段
|
|
@@ -834,7 +931,7 @@ class Base {
|
|
|
* @param array $fields 字段列表
|
|
|
* @return Response
|
|
|
*/
|
|
|
- final public function valid($fields = array()) {
|
|
|
+ public function valid($fields = array()) {
|
|
|
if(!is_array($fields)) {
|
|
|
return Response::FailValidate(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_VALIDATE, 'msg' => '字段必须是数组', 'fields' => []]]);
|
|
|
}
|
|
@@ -848,12 +945,9 @@ class Base {
|
|
|
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);
|
|
|
+ $verify = new Verify($val[0], $values[$field] ?? null, strtolower($valid), $val[1], $val[2] ?? '');
|
|
|
$res = $verify->valid();
|
|
|
if($res->isError()) {
|
|
|
$result[] = $res->getResult() .',获取的是 '. $values[$field];
|
|
@@ -872,10 +966,10 @@ class Base {
|
|
|
/**
|
|
|
* 合并多个 valid 结果 $this->>valids($this->valid(['Uid']), $this->valid(['Nickname', 'Email']));
|
|
|
* @param ...
|
|
|
- * @return mixed|Response
|
|
|
+ * @return mixed|Qii\Driver\Response
|
|
|
* @throws \Exception
|
|
|
*/
|
|
|
- final public function valids() {
|
|
|
+ public function valids() {
|
|
|
$validArr = func_get_args();
|
|
|
if(count($validArr) == 0) {
|
|
|
return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => true]);
|
|
@@ -912,37 +1006,28 @@ class Base {
|
|
|
*/
|
|
|
protected function uniqueCondition() {
|
|
|
$uniqueWhere = [];
|
|
|
+ $uniqueOr = [];
|
|
|
$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;
|
|
|
+ $useWhere = false;
|
|
|
+ if(count($unique) == 1) {
|
|
|
+ $useWhere = true;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
- 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;
|
|
|
+
|
|
|
+ foreach ($unique as $key) {
|
|
|
+ $key = $this->entity()->convertToField($key);
|
|
|
+ $property = $this->entity()->convertToProperty($key);
|
|
|
+ if($useWhere) {
|
|
|
+ $uniqueWhere[$key] = $this->$property;
|
|
|
+ }else{
|
|
|
+ $uniqueOr[$key] = $this->$property;
|
|
|
}
|
|
|
- $uniqueWhere[] = $arr;
|
|
|
}
|
|
|
- return $uniqueWhere;
|
|
|
+ return [$uniqueWhere, $uniqueOr];
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -990,13 +1075,13 @@ class Base {
|
|
|
*
|
|
|
* @return array [$uniqueWhere, $uniqueOr, $excludeCondition, $primaryCondition]
|
|
|
*/
|
|
|
- final public function condition() {
|
|
|
+ public function condition() {
|
|
|
//如果设置了 unique 就先验证唯一性,保存的时候验证 uniqueKey,更新的时候验证uniqueKey并排primaryKey
|
|
|
//保存数据的时候验证uniqueKey;更新时验证 uniqueKey,并且排除 primaryKey,如果uniqueKey == primaryKey则不去做唯一性验证
|
|
|
- $uniqueWhere = $this->uniqueCondition();
|
|
|
+ list($uniqueWhere, $uniqueOr) = $this->uniqueCondition();
|
|
|
$excludeCondition = $this->excludeCondition();
|
|
|
$primaryCondition = $this->primaryCondition();
|
|
|
- return [$uniqueWhere, $excludeCondition, $primaryCondition];
|
|
|
+ return [$uniqueWhere, $uniqueOr, $excludeCondition, $primaryCondition];
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1004,11 +1089,11 @@ class Base {
|
|
|
*
|
|
|
* @return array
|
|
|
*/
|
|
|
- final public function getOrderBy() {
|
|
|
+ public function getOrderBy() {
|
|
|
$order = array();
|
|
|
- $orderBy = (array) $this->orderBy();
|
|
|
+ $orderBy = $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']);
|
|
|
+ $orderBy = call_user_func($this->hooker['order']['func'], $order, $this->hooker['order']['args']);
|
|
|
}
|
|
|
foreach ($orderBy as $key => $val) {
|
|
|
$field = $this->entity()->convertToField($key);
|
|
@@ -1018,7 +1103,7 @@ class Base {
|
|
|
}
|
|
|
$order[$field] = $val;
|
|
|
}
|
|
|
- return (array) $order;
|
|
|
+ return $order;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1072,7 +1157,7 @@ class Base {
|
|
|
*
|
|
|
* @return mixed|\Qii\Driver\Qii\Driver\Response
|
|
|
*/
|
|
|
- final public function response() {
|
|
|
+ public function response() {
|
|
|
$properties = $this->properties();
|
|
|
if(!$properties) {
|
|
|
return Response::Fail(static::class .'::'. __FUNCTION__,
|
|
@@ -1121,7 +1206,7 @@ class Base {
|
|
|
(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]);
|
|
|
+ $func->set($key, $str, ['life_time' => $config['life_time']]);
|
|
|
return $res;
|
|
|
}
|
|
|
}
|