Explorar el Código

Update: entity base新增to array

朱金辉 hace 2 meses
padre
commit
9272ddd97a

+ 1 - 1
composer.json

@@ -19,7 +19,7 @@
     },
     "minimum-stability": "dev",
     "require": {
-        "php": ">=5.5",
+        "php": ">=7.0",
         "ext-gd" : ">=2.1.0"
     }
 }

+ 44 - 12
src/Driver/Base.php

@@ -118,7 +118,7 @@ class Base
      * 查询一行
      * @param $table
      * @param null $where
-     * @return mixed
+     * @return array | bool
      * @throws \Exception
      */
     public function selectRow($table, $where = null)
@@ -130,10 +130,22 @@ class Base
         $this->modelSQL = $sql = $this->createSelectSQL($table);
         return $this->getRow($sql);
     }
+
+    /**
+     * get row 子类去覆写
+     *
+     * @param $sql
+     * @return false
+     */
+    public function getRow($sql) {
+        return false;
+    }
     /**
      *
      * 查询一列
-     * @param String $table
+     * @param string $table 表名
+     * @return false | array
+     * @throws TableException
      */
     final function selectOne($table)
     {
@@ -149,6 +161,15 @@ class Base
     }
 
     /**
+     * get one 方法, 子类去覆写
+     * @param string $sql
+     * @return false | array
+     */
+    public function getOne($sql) {
+        return false;
+    }
+
+    /**
      * 插入数据
      * @param $table
      * @param $dataArray
@@ -554,7 +575,7 @@ class Base
      * @return $this
      * @throws \Exception
      */
-    public function join($val, &$res = null) {
+    public function join($val, &$res = null, $joinType = 'leftJoin') {
         if(!is_array($val)) {
             if(!empty($val)) {
                 $this->joinCondition[] = $val;
@@ -565,7 +586,7 @@ class Base
             return $this;
         }
         $slices = $this->groupContents($val);
-        $this->handleTableJoin($slices, 'leftJoin', $res);
+        $this->handleTableJoin($slices, $joinType, $res);
         return $this;
     }
 
@@ -612,7 +633,7 @@ class Base
     /**
      * Order by
      *
-     * @param mix $order
+     * @param array|string $order
      * @return $this
      * @throws \Exception
      */
@@ -661,7 +682,7 @@ class Base
     /**
      * 过滤值
      *
-     * @param mix $word
+     * @param string|array $word
      * @return array|string
      */
     final function setQuote($word)
@@ -677,11 +698,11 @@ class Base
     /**
      *
      * 查询的字段
-     * @param String $fields
+     * @param string|array $fields
+     * @return $this
      */
     final function fields($fields = "*")
     {
-        $this->fields = null;
         if (empty($fields)) $fields = "*";
         if (is_array($fields)) {
             if(count($fields) == 0) {
@@ -736,7 +757,7 @@ class Base
     /**
      * 返回response对象
      *
-     * @return Bool
+     * @return Response
      */
     public function getResponse()
     {
@@ -762,7 +783,7 @@ class Base
     /**
      * 执行Model过程中保存的相关信息
      *
-     * @param String $option
+     * @param string $option
      * @return mixed
      */
     final function querySQL($option = '')
@@ -889,6 +910,7 @@ class Base
         }
         return $res;
     }
+
     /**
      * 把条件根据『链接字符串,『字段:值』』等内容分组
      *
@@ -914,6 +936,7 @@ class Base
      *   );
      * @param $group
      * @return array [['or/and', 'like/equal/...', ['字段1' => '值1', '字段2' => '值2']],[...]]
+     * @throws \Exception
      */
     protected function groupContents($group)
     {
@@ -985,7 +1008,7 @@ class Base
     /**
      * 是否是操作表
      *
-     * @param mix $val 值
+     * @param string $val 值
      * @return bool
      */
     protected function isOperateTable($val)
@@ -1013,7 +1036,16 @@ class Base
             $extraParams = array_slice(func_get_args(), 2);
         }
         $where = array();
-        $operator = array('equal' => "%s`%s` = '%s'",'in' => "%s`%s` in (%s)", 'unequal' => "%s`%s` != '%s'", 'greater' => "%s`%s` > '%s'", 'greaterEqual' => "%s`%s` >= '%s'", 'gte' => "%s`%s` >= '%s'", 'less' => "%s`%s` < '%s'", 'lessEqual' => "%s`%s` <= '%s'", 'lte' => "%s`%s` <= '%s'", 'like' => "%s`%s` like '%%%s%%'");
+        $operator = array('equal' => "%s`%s` = '%s'",
+                            'in' => "%s`%s` in (%s)",
+                            'unequal' => "%s`%s` != '%s'",
+                            'greater' => "%s`%s` > '%s'",
+                            'greaterEqual' => "%s`%s` >= '%s'",
+                            'gte' => "%s`%s` >= '%s'",
+                            'less' => "%s`%s` < '%s'",
+                            'lessEqual' => "%s`%s` <= '%s'",
+                            'lte' => "%s`%s` <= '%s'",
+                            'like' => "%s`%s` like '%%%s%%'");
         $lastIsOperator = false;
         $lastIsValue = null;
         $i = 0;

+ 307 - 92
src/Driver/Entity/Base.php

@@ -49,22 +49,56 @@ class Base {
      * 目前 where 和 order 及 fields 支持
      * @param $key
      * @param $hooker
-     * @return void
+     * @return $this
      */
     protected function setHooker($key, $hooker, $args) {
         $this->hooker[$key]['func'] = $hooker;
         $this->hooker[$key]['args'] = $args;
+        return $this;
     }
 
     /**
+     * Or Hooker
+     * @param $hooker
+     * @param $args
+     * @return $this
+     * @throws \Exception
+     */
+    public function setOrHooker($hooker, $args = null){
+        $this->checkCallable($hooker);
+        if(!isset($this->hooker['or'])) {
+            $this->hooker['or'] = [];
+        }
+        $this->hooker['or'][] = ['func' => $hooker, 'args' => $args];
+        return $this;
+    }
+
+    /**
+     * 获取or条件
+     *
+     * @return array
+     */
+    public function getOrHooker() {
+        $or = [];
+        if(isset($this->hooker['or'])) {
+            foreach ($this->hooker['or'] as $value) {
+                if(is_callable($value['func'])) {
+                    $or[] = call_user_func($value['func'], [], $value['args']);
+                }
+            }
+        }
+        return $or;
+    }
+    /**
      * 设置where hooker
      * @param object $hooker
-     * @return void
+     * @return $this
      * @throws \Exception
      */
     public function setWhereHooker($hooker, $args = null) {
         $this->checkCallable($hooker);
         $this->setHooker('where', $hooker, $args);
+        return $this;
     }
     /**
      * 获取where条件
@@ -164,7 +198,7 @@ class Base {
     /**
      * 设置关联子查询
      *
-     * @param $hooker
+     * @param $hooker [关联对象, 返回数据key, hasOne/hasMany, 主键, rel 主键]
      * @params $args
      * @return $this
      * @throws \Exception
@@ -181,7 +215,7 @@ class Base {
     /**
      * 获取with hooker
      *
-     * @return mixed|null[]
+     * @return array
      */
     public function getWithHooker() {
         $callback = [];
@@ -261,6 +295,14 @@ class Base {
     }
 
     /**
+     * 返回所有 Fields
+     * @return array
+     */
+    public function fields()
+    {
+        return [];
+    }
+    /**
      * unique (unique 如果是 array 则表示 联合唯一,如果是string则是任意唯一,多个单独唯一使用字符串以逗号隔开, 主键除外)
      *
      * @return mixed
@@ -348,7 +390,7 @@ class Base {
         $properties = $method->getproperties();
         $fields = [];
         foreach($properties as $property) {
-            if($property->isPublic()) {
+            if($property->isPublic() && !$property->isStatic()) {
                 $name = $property->getName();
                 if(!isset($this->$name)) {
                     continue;
@@ -458,23 +500,77 @@ class Base {
     }
     /**
      * 与get不同的这个返回的是Response
-     * @return mixed|\Qii\Driver\Qii\Driver\Response
+     *
+     * @return mixed|Response
      */
     public function info() {
         try{
-            $info = $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->selectRow($this->getTable());
-
-            if($info) {
-                $this->withRow($info);
-            }
+            $info = $this->createQuery()->selectRow($this->getTable());
+            if($info) $this->withRow($info);
             return Response::Success(static::class .'::'. __FUNCTION__,
-                ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '获取成功', 'body' => $info]]
+                [
+                    '_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' => []]
-                ]);
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' =>$e->getMessage(), 'body' => []],
+                    'message' => $e->getMessage()
+                ]
+            );
+        }
+    }
+    /**
+     * 将表对象对应的字段转换成array
+     *
+     * @return array
+     */
+    public function toArray()
+    {
+        $arr = [];
+        $method = new \ReflectionClass($this);
+        $vars = [];
+        foreach ($this as  $k => $t) {
+            if(preg_match("/^[A-Z]+/", $k)) {
+                $vars[] = $k;
+            }
+        }
+        $fields = $this->fields();
+        if(count($fields)) {
+            foreach ($fields as $key => $value) {
+                $arr[$key] = $value;
+            }
+            foreach ($vars as $extra) {
+                if(!isset($arr[$extra])) {
+                    $field = $this->entity()->convertToField($extra);
+                    $arr[$field] = $this->$extra;
+                }
+            }
+            return $arr;
         }
+
+        $properties = $method->getproperties();
+        foreach($properties as $property) {
+            if($property->isPublic() && !$property->isStatic()) {
+                $name = $property->getName();
+                $field = $this->entity()->convertToField($name);
+                $arr[$field] = $this->$name;
+                continue;
+            }
+            //移除非public的变量
+            $i = array_search($property->getName(), $vars);
+            if($i !== false) {
+                array_splice($vars, $i, 1);
+            }
+        }
+        foreach ($vars as $extra) {
+            if(!isset($arr[$extra])) {
+                $field = $this->entity()->convertToField($extra);
+                $arr[$field] = $this->$extra;
+            }
+        }
+        return $arr;
     }
     /**
      * 是否相关数据存在
@@ -508,7 +604,10 @@ class Base {
             $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]]
+                    [
+                        '_result' => ['code' => Response::DOES_EXIST, 'msg' => '数据已经存在', 'body' => $exist],
+                        'message' => '数据已经存在'
+                    ]
                 );
             }
         }
@@ -517,7 +616,10 @@ class Base {
             $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]]
+                    [
+                        '_result' => ['code' => Response::DOES_EXIST, 'msg' => '数据已经存在', 'body' => $exist],
+                        'message' => '数据已存在'
+                    ]
                 );
             }
         }
@@ -527,11 +629,15 @@ class Base {
 
         if($this->db()->isError()) {
             return Response::FailSave(static::class .'::'. __FUNCTION__,
-                ['_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => $this->db()->getMessage(), 'body' => []]
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => $this->db()->getMessage(), 'body' => []],
+                    'message' => $this->db()->getMessage()
                 ]);
         }
         return Response::Success(static::class .'::'. __FUNCTION__,
-            ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '添加成功', 'body' => $res]]
+            [
+                '_result' => ['code' => Response::DO_SUCCESS, 'msg' => '添加成功', 'body' => $res]
+            ]
         );
     }
 
@@ -553,20 +659,28 @@ class Base {
         if($valid->isError()) {
             return $valid;
         }
-        $affectedRows = $this->db()->where($this->getWhereHooker())->delete($this->getTable());
+        $query = $this->db()->where($this->getWhereHooker());
+        $this->handleOrTerm($query);
+        $affectedRows = $query->delete($this->getTable());
         if($this->db()->isError()) {
             return Response::FailSave(static::class .'::'. __FUNCTION__,
-                ['_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => $this->db()->getMessage(), 'body' => []]
-                ]);
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_SAVE, 'msg' => $this->db()->getMessage(), 'body' => []],
+                    'message' => $this->db()->getMessage()
+                ]
+            );
         }
         return Response::Success(static::class .'::'. __FUNCTION__,
-            ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '删除成功,总共删除了'. $affectedRows . '条记录', 'body' => $affectedRows]]
+            [
+                '_result' => ['code' => Response::DO_SUCCESS, 'msg' => '删除成功,总共删除了'. $affectedRows . '条记录', 'body' => $affectedRows],
+                'message' => '删除成功,总共删除了'. $affectedRows . '条记录'
+            ]
         );
     }
     /**
      * 更新
      *
-     * @return mixed | Qii\Driver\Response
+     * @return mixed | Response
      * @throws \Exception
      */
     public function update(){
@@ -620,18 +734,23 @@ class Base {
         $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' => []]]
+                [
+                    '_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]]
+            [
+                '_result' => ['code' => Response::DO_SUCCESS, 'msg' => '数据更新成功,总共更新了'. $affectedRows . '条记录', 'body' => $affectedRows],
+                'message' => '数据更新成功,总共更新了'. $affectedRows . '条记录'
+            ]
         );
     }
 
     /**
      * 更新字段
      *
-     * @return mixed|\Qii\Driver\Qii\Driver\Response|Response
+     * @return mixed| Response
      * @throws \Exception
      */
     public function updateFields() {
@@ -675,7 +794,10 @@ class Base {
         $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' => []]]
+                [
+                    '_result' => ['code' => Response::DOES_NOT_EXIST, 'msg' => '未找到相关记录', 'body' => []],
+                    'message' => '未找到相关记录'
+                ]
             );
         }
         //获取默认值
@@ -686,18 +808,23 @@ class Base {
         $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' => []]]
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_UPDATE, 'msg' => $this->db()->getMessage(), 'body' => []],
+                    'message' => $this->db()->getMessage()
+                ]
             );
         }
         return Response::Success(static::class .'::'. __FUNCTION__,
-            ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => '数据更新成功', 'body' => $affectedRows]]
+            [
+                '_result' => ['code' => Response::DO_SUCCESS, 'msg' => '数据更新成功', 'body' => $affectedRows]
+            ]
         );
     }
 
     /**
      * 增加或减少某一个字段的值
      *
-     * @return mixed|Qii\Driver\Response
+     * @return mixed|Response
      * @throws \Exception
      */
     public function incr() {
@@ -713,7 +840,12 @@ class Base {
         }
         $diff = array_diff_assoc($incr, $primary);
         if(count($diff) == 0) {
-            return Response::Fail(self::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::DO_FAIL, 'msg' => 'INCR 参数错误']]);
+            return Response::Fail(self::class .'::'. __FUNCTION__,
+                [
+                    '_result' => ['code' => Response::DO_FAIL, 'msg' => 'INCR 参数错误'],
+                    'message' => 'INCR 参数错误',
+                ]
+            );
         }
         $sets = [];
         foreach ($diff as $key => $val) {
@@ -729,18 +861,35 @@ class Base {
 
         if($this->db()->isError()) {
             return Response::FailUpdate(static::class .'::'. __FUNCTION__,
-                ['_result' => ['code' => Response::FAIL_FOR_UPDATE, 'msg' => $this->db()->getMessage(), 'body' => []]]
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_UPDATE, 'msg' => $this->db()->getMessage(), 'body' => []],
+                    'message' => $this->db()->getMessage()
+                ]
             );
         }
         return Response::Success(static::class .'::'. __FUNCTION__,
-            ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'INCR 成功', 'body' => $affectedRows]]
+            [
+                '_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'INCR 成功', 'body' => $affectedRows]
+            ]
         );
     }
-
+    /**
+     * 获取where及or条件并创建查询条件
+     *
+     * @return \Qii\Driver\Base
+     */
+    public function createQuery() {
+        $query = $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker());
+        $or = $this->getOrHooker();
+        foreach ($or as $v) {
+            $query = $query->orTerms($v);
+        }
+        return $query;
+    }
     /**
      * 获取第一条数据
      *
-     * @return mixed|\Qii\Driver\Response
+     * @return mixed|Response
      * @throws \Exception
      */
     public function first() {
@@ -748,21 +897,29 @@ class Base {
         foreach ($orderBy as $key => $value) {
             $orderBy[$key] = 'ASC';
         }
-        $row = $this->db()->orderBy($orderBy)->limit(1)->selectRow($this->getTable());
+        $query = $this->createQuery();
+        $row = $query->limit(1)->orderBy($orderBy)->selectRow($this->getTable());
         if($this->db()->isError()) {
-            return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => 'Query 失败', 'body' => []]]);
+            return Response::Fail(static::class .'::'. __FUNCTION__,
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => 'Query 失败' . $this->db()->getMessage(), 'body' => []],
+                    'message' => $this->db()->getMessage()
+                ]
+            );
         }
         if($row) {
             $this->withRow($row);
         }
         return Response::Success(static::class .'::'. __FUNCTION__,
-            ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'Query 成功', 'body' => $row]]
+            [
+                '_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'Query 成功', 'body' => $row]
+            ]
         );
     }
     /**
      * 获取第一条数据
      *
-     * @return mixed|\Qii\Driver\Response
+     * @return mixed|Response
      * @throws \Exception
      */
     public function last() {
@@ -770,15 +927,22 @@ class Base {
         foreach ($orderBy as $key => $value) {
             $orderBy[$key] = 'DESC';
         }
-        $row = $this->db()->fields($this->getFieldsHooker())->orderBy($orderBy)->limit(1)->selectRow($this->getTable());
+        $row = $this->createQuery()->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::Fail(static::class .'::'. __FUNCTION__,
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_SELECT, 'msg' => 'Query 失败', 'body' => []],
+                    'messsage' => $this->db()->getMessage()
+                ]
+            );
         }
         if($row) {
             $this->withRow($row);
         }
         return Response::Success(static::class .'::'. __FUNCTION__,
-            ['_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'Query 成功', 'body' => $row]]
+            [
+                '_result' => ['code' => Response::DO_SUCCESS, 'msg' => 'Query 成功', 'body' => $row]
+            ]
         );
     }
 
@@ -794,7 +958,7 @@ class Base {
         }
         $hooks = $this->getWithHooker();
         foreach ($hooks as $with) {
-            if(!is_array($with) || count($with) != 5 || !is_object($with[0])) {
+            if(!is_array($with) || count($with) < 5 || !is_object($with[0])) {
                 continue;
             }
             $callable = $with[0];
@@ -802,12 +966,18 @@ class Base {
             $method = $with[2];
             $foreignKey = $with[3];
             $associationForeignkey = $with[4];
+            $fields = [];
+            if(count($with) >= 6) {
+                $fields = $with[5];
+            }
             $row[$relField] = [];
             if(!isset($row[$foreignKey])) {
                 continue;
             }
-            $params = [$associationForeignkey,
-                [$associationForeignkey  => $row[$foreignKey]]
+            $params = [
+                $associationForeignkey,
+                [$associationForeignkey  => $row[$foreignKey]],
+                $fields
             ];
             $res = call_user_func_array(array($callable, $method), $params);
 
@@ -828,7 +998,7 @@ class Base {
         if(!$this->initPages($data, $count, $page, $pageSize)) {
             return $data;
         }
-        $lists = $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->limit($data['pages']['limitStart'], $pageSize)->selectRows($this->getTable());
+        $lists = $this->createQuery()->orderBy($this->getOrderBy())->limit($data['pages']['limitStart'], $pageSize)->selectRows($this->getTable());
         $this->withList($lists);
         $data['lists'] = $lists;
         return $data;
@@ -845,35 +1015,41 @@ class Base {
         }
         $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];
-                    }
+            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];
+            $fields = [];
+            if(count($with) == 6) {
+                $fields = $with[5];
+            }
+            $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]];
-                    }
+            }
+            // [rel key, where]
+            $params = [
+                $associationForeignkey,
+                [$associationForeignkey . ':in' => array_unique($rel)],
+                $fields
+            ];
+            $res = call_user_func_array(array($callable, $method), $params);
+            foreach ($lists as &$v) {
+                if(isset($res[$v[$foreignKey]])) {
+                    $v[$relField] = $res[$v[$foreignKey]];
                 }
             }
         }
     }
     /**
      * 关联查询 has one
-     * params[rel_key, where]
+     * params[rel_key, where, fields]
      *
      * @return array
      * @throws \Exception
@@ -881,9 +1057,14 @@ class Base {
     public function hasOne() {
         $args = func_get_args();
         $relKey = $args[0];
-        $res = $this->db()->where($args[1])->rs($this->getTable());
+        $fields = [];
+        if(count($args) == 3 && !empty($args[2])) {
+            $fields = $args[2];
+            if(!in_array($relKey, $fields)) $fields[] = $relKey;
+        }
+        $res = $this->db()->fields($fields)->where($args[1])->rs($this->getTable());
         $rows = [];
-        foreach($res as $k => $v) {
+        foreach($res as $v) {
             $rows[$v[$relKey]] = $v;
         }
         return $rows;
@@ -891,7 +1072,7 @@ class Base {
 
     /**
      * 关联查询
-     *  params[rel_key, where]
+     *  params[rel_key, where, fields]
      *
      * @return array
      * @throws \Exception
@@ -900,9 +1081,15 @@ class Base {
     {
         $args = func_get_args();
         $relKey = $args[0];
-        $res = $this->db()->where($args[1])->rs($this->getTable());
+        $fields = [];
+        if(count($args) == 3 && !empty($args[2])) {
+            $fields = $args[2];
+            if(!in_array($relKey, $fields)) $fields[] = $relKey;
+        }
+
+        $res = $this->db()->fields($fields)->where($args[1])->rs($this->getTable());
         $rows = [];
-        foreach($res as $k => $v) {
+        foreach($res as $v) {
             $rows[$v[$relKey]][] = $v;
         }
         return $rows;
@@ -917,13 +1104,22 @@ class Base {
      */
     public function listAll() {
         $limit = $this->getLimitHooker();
+        $query = $this->createQuery()->orderBy($this->getOrderBy());
         if(empty($limit) || !is_array($limit)) {
-            return $this->db()->fields($this->getFieldsHooker())->where($this->getWhereHooker())->orderBy($this->getOrderBy())->selectRows($this->getTable());
+            $list =  $query
+                ->selectRows($this->getTable());
+            $this->withList($list);
+            return $list;
         }
         if(count($limit) == 1) {
-            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])->selectRows($this->getTable());
+            $list = $query->limit($limit[0])->selectRows($this->getTable());
+            $this->withList($list);
+            return $list;
+        }
+        $list =  $query
+            ->limit($limit[0], $limit[1])->selectRows($this->getTable());
+        $this->withList($list);
+        return $list;
     }
     /**
      * 验证相关字段
@@ -933,7 +1129,12 @@ class Base {
      */
     public function valid($fields = array()) {
         if(!is_array($fields)) {
-            return Response::FailValidate(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_VALIDATE, 'msg' => '字段必须是数组', 'fields' => []]]);
+            return Response::FailValidate(static::class .'::'. __FUNCTION__,
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_VALIDATE, 'msg' => '字段必须是数组', 'fields' => []],
+                    'message' => '字段必须是数组'
+                ]
+            );
         }
         $rules = $this->rules();
         $result = [];
@@ -950,7 +1151,7 @@ class Base {
                 $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];
+                    $result[] = $res->getResult() .',获取的是'. ($values[$field] ?? '空');
                     if(!in_array($field, $invalidKey)) {
                         $invalidKey[] = $field;
                     }
@@ -958,15 +1159,20 @@ class Base {
             }
         }
         if(count($result) > 0) {
-            return Response::FailValidate(static::class .'::'. __FUNCTION__, ['_result' => ['code' => Response::FAIL_FOR_VALIDATE, 'msg' => $result, 'fields' => $invalidKey]]);
+            return Response::FailValidate(static::class .'::'. __FUNCTION__,
+                [
+                    '_result' => ['code' => Response::FAIL_FOR_VALIDATE, 'msg' => $result, 'fields' => $invalidKey],
+                    'message' => join("\n", $result)
+                ]
+            );
         }
         return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => true]);
     }
 
     /**
-     * 合并多个 valid 结果 $this->>valids($this->valid(['Uid']), $this->valid(['Nickname', 'Email']));
+     * 合并多个 valid 结果 $this->valids($this->valid(['Uid']), $this->valid(['Nickname', 'Email']));
      * @param ...
-     * @return mixed|Qii\Driver\Response
+     * @return mixed|Response
      * @throws \Exception
      */
     public function valids() {
@@ -984,7 +1190,7 @@ class Base {
 
         foreach ($validArr as $valid) {
             if(!($valid instanceof Response)) {
-                throw new \Exception('验证结果类型必须是\Qii\Drive\Response类型');
+                throw new \Exception('验证结果类型必须是\Qii\Driver\Response类型');
             }
             if($valid->isError()) {
                 $result = $valid->getResult();
@@ -993,7 +1199,10 @@ class Base {
             }
         }
         if(count($invalid['message']) > 0) {
-            return Response::Fail(static::class .'::'. __FUNCTION__, ['_result' => ['message' => $invalid['message'], 'fields' => $invalid['fields']]]);
+            return Response::Fail(static::class .'::'. __FUNCTION__, [
+                '_result' => ['message' => $invalid['message'], 'fields' => $invalid['fields']],
+                'message' => $invalid['message']
+            ]);
         }
         return Response::Success(static::class .'::'. __FUNCTION__, ['_result' => true]);
     }
@@ -1127,11 +1336,7 @@ class Base {
         if ($data['pages']['currentPage'] > $data['pages']['totalPage']) {
             return false;
         }
-        $frames = array(
-            'left' => 0,
-            'right' => 0
-        );
-        $pagination = $pagination < $data['pages']['totalPage'] ? $pagination : $data['pages']['totalPage'];
+        $pagination = min($pagination, $data['pages']['totalPage']);
 
         if($data['pages']['currentPage'] - floor($pagination / 2) <= 0) {
             $frames['left'] = 1;
@@ -1155,7 +1360,7 @@ class Base {
     /**
      * response as object
      *
-     * @return mixed|\Qii\Driver\Qii\Driver\Response
+     * @return mixed|Response
      */
     public function response() {
         $properties = $this->properties();
@@ -1203,13 +1408,23 @@ class Base {
                     }
                 }
                 $expiredAt = isset($config['life_time']) ? (int) $config['life_time'] :
-                    (isset($policy['life_time']) ? $policy['life_time'] : $this->defaultExpired);
+                    ($policy['life_time'] ?? $this->defaultExpired);
                 $res = call_user_func_array(array($this, $method), $args);
                 $str = serialize($res);
-                $func->set($key, $str, ['life_time' => $config['life_time']]);
+                $func->set($key, $str, ['life_time' => $expiredAt]);
                 return $res;
             }
         }
         return call_user_func_array(array($this->db(), $method), $args);
     }
+
+    /**
+     * 验证规则,由子类继承去修改
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [];
+    }
 }

+ 36 - 18
src/Driver/Entity/Entity.php

@@ -1,8 +1,6 @@
 <?php
 namespace Qii\Driver\Entity;
 
-use Qii\Driver\Model;
-
 /**
  * 通过数据表生成 entity
  * 使用方法:
@@ -149,15 +147,33 @@ class Entity {
         }
         if(count($dynamicProperty)) {
             $classAndProperty[] = <<<DOC
-    /**
-     * 动态变化的日期,初始化的时候赋值
-     */
+        /**
+         * 动态变化的日期,初始化的时候赋值
+         */
 DOC;
             ;
             $classAndProperty[] = "\tpublic function __construct(){";
             $classAndProperty[] = "\n";
             $classAndProperty[] = "\t}";
 
+            $classAndProperty[] = <<<DOC
+
+        /**
+         * 获取表名
+         */
+        public function getTable(){
+            return '{$table}';
+        }
+DOC;
+            $fields = join("', '", $tableInfo['fields']);
+            $classAndProperty[] = <<<DOC
+    /**
+     * 数据表中的所有字段
+     */
+     public function fields(){
+        return array('$fields');
+     }
+DOC;
             $classAndProperty[] = "\t/**";
             $classAndProperty[] = "\t * 设置默认值";
             $classAndProperty[] = "\t */";
@@ -173,16 +189,6 @@ DOC;
             $classAndProperty[] = "\t\treturn \$defaultValue;";
             $classAndProperty[] = "\t}";
         }
-        $classAndProperty[] = <<<DOC
-
-\t/**
-\t * 获取表名
-\t */
-\tpublic function getTable(){
-\t\treturn '{$table}';
-\t}
-DOC;
-
         //生成 table rules
         $classAndProperty[] = $this->generateRules($tableInfo);
         $classAndProperty[] = '}';
@@ -230,15 +236,28 @@ DOC;
         }, function($tableInfo, $constantJoin){
             return $constantJoin;
         })($tableInfo, $constantJoin);
-
         $primaryKey = [];
-        if(isset($tableInfo['rules']['extra']) && isset($tableInfo['rules']['extra']['auto_increment'])) {
+        $autoIncrement = '';
+        if(isset($tableInfo['rules']['extra']['auto_increment'])) {
             $primaryKey = $tableInfo['rules']['extra']['auto_increment'];
+            $autoIncrement = $tableInfo['rules']['extra']['auto_increment'][0];
         }
         $next[] = "\t\treturn ". '$rules;';
         $next[] = "\t". '}';
         $next[] = <<<DOC
     /**
+     * 自增字段
+     * 
+     * @return string
+     */
+     public function autoIncrement(){
+        return '$autoIncrement';
+     }
+DOC;
+
+
+        $next [] = <<<DOC
+    /**
      * unique (unique 如果是 array 则表示 联合唯一,如果是string则是任意唯一,多个单独唯一使用字符串以逗号隔开, 主键除外)
      *
      * @return mixed
@@ -266,7 +285,6 @@ DOC;
 
         $next[] = <<<DOC
     }
-
     /**
      * 保存数据的时候,验证唯一需要排除的值,此处仅支持,单个或联合排除,不支持单个排除
      *

+ 9 - 0
src/Driver/Model.php

@@ -129,6 +129,15 @@ class Model
     }
 
     /**
+     * 是否有错误产生
+     *
+     * @return false
+     */
+    public function isError()
+    {
+        return false;
+    }
+    /**
      * 获取当前使用的数据库
      */
     public function getCurrentDB()

+ 1 - 1
src/Driver/Pdo/Driver.php

@@ -180,7 +180,7 @@ class Driver extends Base implements Intf
     /**
      * 获取一行
      * @var string $sql 获取一行
-     * @return array 返回数据
+     * @return array | false 返回数据
      */
     public function getRow($sql)
     {

+ 3 - 3
src/Driver/Response.php

@@ -214,7 +214,7 @@ class Response
 	 * 保存失败
 	 * @param string $operate 操作类型
 	 * @param mixed $result 结果
-	 * @return Qii\Driver\Response|mixed
+	 * @return \Qii\Driver\Response|mixed
 	 */
 	public static function FailSave($operate, $result)
 	{
@@ -234,7 +234,7 @@ class Response
 	 * 更新失败
 	 * @param string $operate 操作类型
 	 * @param mixed $result 结果
-	 * @return Qii\Driver\Response|mixed
+	 * @return \Qii\Driver\Response|mixed
 	 */
 	public static function FailUpdate($operate, $result)
 	{
@@ -316,7 +316,7 @@ class Response
 	public function getResult($key = '_result')
 	{
 		if ($key) {
-			return isset($this->body['result']) && isset($this->body['result'][$key]) ? $this->body['result'][$key] : null;
+			return $this->body['result'][$key] ?? null;
 		}
 		return $this->body['result'];
 	}