# TOP-Framework *这是一个部分代码源自三年前毕业设计中的代码集合,后经过一系列重构,形成的一套框架。在此准备写一个文档。* ## 模块 ### 创建模块 1. 手动创建 在application(可更改)目录下创建home目录,再创建config、controller(必须)、model、view目录 2. 命令行自动创建 命令格式([]为可选参数): ``` php create.php 目录 模块名 [入口文件] ``` 进入framework/create/目录,执行以下命令: ``` php create.php application home index ``` 至此,已经通过简单的命令创建了home模块,浏览器输入127.0.0.1即可访问home模块(系统默认模块为home模块,可在入口文件中指定),亦可命令行访问home模块。 ## 控制器 ### 创建控制器 一个典型的控制器(Index.php) ``` view(); } ``` 调用基础控制器中的view方法、并return出去,完成模板的展示。 ### 模板传值 1. view方法 ``` public function index() { return $this->view(null, [ 'param' => 'Hello world!' ]); } ``` 2. 直接return数组 ``` public function index() { return [ 'param' => 'Hello world!' ]; } ``` 以上两种方式等效。 ### 控制器方法的前置、后置操作 ``` public function before_index() { } public function after_index() { } public function index() { return [ 'param' => 'Hello world!' ]; } ``` 命名规范:before_方法名(前置)、after_方法名(后置),执行index方法之前会先执行before_index方法(如果存在),执行完index方法后会执行after_index方法(如果存在)。当前置方法return的值为空字符串、null、true时才会继续执行,否则前置方法的return等效于index方法的return。 ## 模型 ### 创建模型 一个典型的模型(Users.php) ``` update([ 'username' => 'TOP糯米' ], 1); ``` 除此之外,提供另一种方式,传递更多条件或更复杂的条件 ``` $this->update([ 'username' => 'TOP糯米' ], function ($model) { $model->where('id', 1); }); ``` 当然,也可以使用连贯操作 ``` $this->where('id', 1)->update([ 'username' => 'TOP糯米' ]); ``` 成功返回受影响的记录数,失败抛出DatabaseException异常。 5. find($param = false, $notRaw = true) 查找一条记录 可传入第一个参数为主键,第二个参数为是否按指定的规则(outReplace属性)进行处理。 一般调用 ``` $this->find(1); ``` 匿名函数 ``` $this->find(function ($model) { $model->where('id', 1); }); ``` 连贯操作 ``` $this->where('id', 1)->find(); ``` 成功返回一个一维数组,失败抛出DatabaseException异常。 6. select($param = false, $notRaw = true) 查找多条记录 使用方法同find 成功返回一个二维数组,失败抛出DatabaseException异常。 7. delete 删除记录 直接传入主键 ``` $this->delete(1); ``` 匿名函数 ``` $this->delete(function () { $model->where('id', 1); }); ``` 连贯操作 ``` $this->where('id', 1)->delete(); ``` 成功返回受影响的记录数,失败抛出DatabaseException异常。 8. count 返回记录数 一般调用 ``` $this->count(); ``` 第一个参数同样可以为匿名函数、并且同样支持连贯操作 成功返回记录数,失败抛出DatabaseException异常。 9. avg 计算平均值 接收一个参数,当没有使用field方法指定字段时,可直接传入字段名,以计算平均值。 ``` $this->avg('score'); ``` 使用field方法指定字段 ``` $this->field('score')->avg(); ``` 匿名函数中指定字段或条件 ``` $this->avg(function ($model) { $model->where('score', '>=', 60); $model->field('score'); }); ``` 成功返回平均值,失败抛出DatabaseException异常。 10. max 计算最大值 同avg方法 11. min 计算最小值 同avg方法 12. sum 求和 同avg方法 13. _sql 返回最后执行的SQL语句 14. tableDesc 返回表结构 接收参数为一个完整表名。 成功返回表结构,失败抛出DatabaseException异常。 15. distinct 过滤记录中的重复值 接收一个为字段名称的参数 调用 ``` $this->distinct('sex')->select(); ``` 失败抛出DatabaseException异常。 16. effect 删除时指定表(别)名 接收一个参数,可以为字符串或数组,参数为表名或表别名 调用 ``` $this->delete(function ($model) { $model->effect('s,this'); $model->join('left', 'score', 's')->on('s.uid = this.id'); $model->where(['this.id' => 3]); }); ``` 17. field 指定字段 可传入字符串或数组 18. where 指定条件 最多可接收三个参数 仅传入一个参数时,可传入字符串或数组 ``` $where = ['id' => ['>', 10], 'sex' => 1]; $where = 'id > 10 and sex = 1'; $this->where($where)->select(); ``` 两个参数,解析为“字段=值” ``` $this->where('sex', 1)->select(); ``` 三个参数,指定字段与字段值的连接符 ``` $this->where('sex', '>', 1)->select(); ``` 19. order 对结果进行排序 ``` $this->order('id desc')->select(); ``` 也可以使用匿名函数调用order方法 20. limit 查询范围 接收一个参数,可以是字符串或数组 一般调用 ``` $this->limit('0, 5')->select(); $this->limit([0, 5])->select(); ``` 两种方式等效 21. join 加入多表进行查询,通常情况下与on方法同时使用 接收三个参数,第一个参数为连接方式(空、left、right、full),第二个参数为表名(不包含前缀),第三个参数为别名(当前表会自动将”this“作为别名)。 一般调用 ``` $this->select(function ($model) { $model->join('left', 'score', 's')->on('s.uid = this.id'); }); ``` 同样也可以使用连贯操作 22. on 表字段连接关系 见join方法 #### 属性: 1. $table 指定当前模型的表名(优先于模型名称) ``` protected $table = 'users'; ``` 2. $pk 指定当前模型的主键(如果不指定,程序将自动查询以当前模型命名的表的主键) ``` protected $pk = 'id'; ``` 3. $map 指定传入数据的键与数据库字段名称的映射关系 ``` protected $map = [ 'name' => 'username' ]; ``` 4. $inReplace 入库时替换值 数据入库时自动格式化时间为unix时间戳 ``` protected $inReplace = [ 'create_time' => ['formatTime', true] ]; protected function formatTime($time) { return strtotime($time); } ``` 至此,在数据在被写入数据库之前会先调用inReplace中设定的函数、方法,并将return的值作为新的值写入数据库。 注意:当以字段为键名的数组的值为一个字符串时,则该字符串为即将调用的函数,如果值为一个数组,且无第二个值或第二个值为false、空,则该数组第一个值为即将调用的函数,如第二个值为true,则表示当前调用的方法存在于本类或父类中。 5. $outReplace 出库时替换值 ``` protected $outReplace = [ 'sex' => ['outFormatSex', true] ]; protected function outFormatSex($sex) { switch ($sex) { case 1: return '男'; break; case 2: return '女'; break; default: return '未知'; } } ``` 注意:当以字段为键名的数组的值为一个字符串时,则该字符串为即将调用的函数,如果值为一个数组,且无第二个值或第二个值为false、空,则该数组第一个值为即将调用的函数,如第二个值为true,则表示当前调用的方法存在于本类或父类中。 6. $updateReplace 数据更新时替换值 基本类似于inReplace,但仅当执行更新操作时执行。 7. $validate 自动验证 验证不为空 ``` protected $validate = [ 'username' => ['notNull', '用户名不能为空'], ]; ``` 验证不等于 ``` protected $validate = [ 'username' => ['notEqual', '0', '用户名不能为0'], ]; ``` 多条件(用户名不为空且不为0) ``` protected $validate = [ 'username' => [ ['notNull', '用户名不能为空'], ['notEqual', '0', '用户名不能为0'], ], ]; ``` 自定义函数验证,新建函数demo到函数库 ``` function demo($name, $n1, $n2) { if ($name == $n1 || $name == $n2) { return false; } return true; } ``` 添加到自动验证 ``` protected $validate = [ 'username' => [ ['notNull', '用户名不能为空'], ['notEqual', '0', '用户名不能为0'], ['demo', 'TOP糯米', '张三', '用户名不能为TOP糯米或张三'], ], ]; ``` ### 调用模型 调用模型有两种方式: 1. model函数(推荐) model函数会返回一个模型的单例,使用方式与直接new无差别。 ``` $object = model(模型); ``` 2. new 模型 ``` $object = new 模型(); ``` ## 模板 ### 模板继承 模板继承通过extend标签与block标签配合使用实现。 一个最简单的继承 ``` // Base/layout.html(父级模板)