# zhlphp **Repository Path**: juheli/zhlphp ## Basic Information - **Project Name**: zhlphp - **Description**: ZHLPHP是一个开源、简单、快速、低耦合,高扩展,低门槛的PHP开发框架。 - **Primary Language**: PHP - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: https://www.yj521.com - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2022-04-07 - **Last Updated**: 2024-04-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ZHLPHP 使用说明 # 简介 > ZHLPHP是一个开源、简单、快速、低耦合,高扩展,低门槛的PHP开发框架,遵循 Apache2.0 开源许可协议发布,可以免费使用。 > 小、精、简,无需学习沉重的框架语法,只需要了解框架目录结构以及了解php语法会写if判断和foreach数组遍历即可使用该框架。 > 本框架主要应用到web相关项目中,更多丰富内容支持自定义扩展,可以根据自己风格封装成属于自己的框架和应用项目。 # 一、安装 >* 下载并解压到服务根目录下即可。 >* 注意:app目录下的文件为示例,建议删除(app目录不要删除),实际开发根据业务而定功能模块。 # 二、目录结构 ``` ├── app ------------------- 应用目录(如果想重新命名同时修改核心文件SYS_APP_PATH参数) ├── config ---------------- 应用配置文件目录 │ └── config.php -------- 自定义全局变量参数配置文件 │ └── database.php ------ 数据库配置文件 ├── extend ---------------- 第三方扩展类库 │ └── Function.php ------ 自定义函数扩展文件(非必须,可删除,应用时需要引入) ├── public ---------------- 静态资源存放目录(比如css,js,image,uploads等) ├── runtime --------------- 系统缓存日志等目录 │ ├── error ------------- 系统日志存放目录 │ ├── db ---------------- 自定义sql打印日志存放目录, 调用系统辅助函数SYS_DB_LOGER($s) │ └── logs -------------- 自定义打印日志存放目录, 调用系统辅助函数SYS_LOGER($s) ├── zhlphp ---------------- 框架核心文件目录 └── .gitignore ------------ Git忽略配置文件(可删除) └── .htaccess ------------- Apache,分布式配置文件(可放到public目录下) └── 404.html -------------- 404页面(可删除,建议保留,可放到public目录下) └── index.php ------------- 应用程序框架入口文件(可放到public目录下需要注意附件根目录设置) └── LICENSE --------------- 发布协议(可删除) └── nginx.conf ------------ Nginx配置文件(可放到public目录下) └── README.md ------------- 说明文档(可删除) └── web.config ------------ ISS配置文件(可放到public目录下) ``` >`app`应用目录使用方式是`app`目录下创建一个文件夹(功能模块),里边分别`controllers`、`serves`、`models`、`views`,比如创建web和admin: ``` ├── web -------------------------------- [自定义]功能模块目录(比如当前为前台) │ ├── controllers -------------------- [勿改名]控制器目录 │ │ └── Web_BaseController.php ----- 类不存在默认定向指定类(可自定义可配合404页面使用) │ │ └── Web_IndexController.php ---- [自定义]控制器文件 │ ├── models ------------------------- [勿改名]模型目录 │ │ └── Web_CommModel.php ---------- [自定义]模型文件(主要数据交互) │ ├── serves ------------------------- 服务层目录 │ │ └── Web_CommServe.php ---------- [自定义]服务文件(主要业务逻辑) │ ├── views -------------------------- [勿改名]视图目录 │ │ ├── web_index ------------------ [自定义]视图目录(一般根据控制器命名,可自定义) │ │ │ └── about.php -------------- [自定义]视图文件(控制器里的方法名) │ │ │ └── common.php ------------- [自定义]w_index目录下公共父级模版视图,会覆盖上级目录common.php │ │ │ └── index.php -------------- [自定义]视图文件(控制器里的方法名) │ │ └── common.php ----------------- [自定义]当前模块下所有控制器父级模版视图(控制器displays方法才起作用) ├── admin ------------------------------ [自定义]功能模块目录(比如当前为后台,目录结构参考web) ``` # 三、运行 ## 1、运行条件 ### (1)、环境 > Apache / Nginx / ISS + PHP + MYSQL / ORACLE > * php5.3以上版本(推荐php7) > * mysql5以上版本(如果需要链接数据库时要求) > * php运行环境(如Apache, Nginx, IIS) ### (2)、扩展 > >| __扩展名__ | __类型__ | __说明__ | >| ---------- | ----------- | -------- | >| openssl | 必须 | 框架内置加密函数必须开启 | >| pdo | 数据库需要 | 如果使用数据库pdo需要开启 | >| mysqli | 数据库需要 | 如果使用mysqli连接需要开启 | >| oci8 | 数据库需要 | 如果使用oracle数据库需要开启 | >| gd2 | 常用 | 如果用到文件上传需要开启 | >| curl | 常用 | 如果用到curl需要开启 | >| mbstring | 常用 | 如果用到mb_strlen()等需要开启 | >| 其他…… | 常用 | 根据业务需要自行开启需要的扩展 | ### (3)、配置 > 1、index.php 入口文件(放到不同的目录下注意附件根目录参数配置) > 2、Apache 服务需要配置`.htaccess`文件(直接配置项目跟目录下.htaccess) > 3、Nginx 服务需要配置`nginx.conf`文件(配置Nginx的对应的nginx.conf文件) > 4、IIS 服务需要配置`web.config`文件(直接配置项目跟目录下web.config) > 当前已经初始配置,详细配置见文档后部分“伪静态配置”。 > ## 2、框架运行流程 >* index.php -> /zhlphp/Base.php -> /zhlphp/core/Core.php -> {控制器C} (往后非必须)-> {服务层S} -> {模型M} -> {视图V},或者控制器直接到视图。 ## 3、URL结构组成和解析 >* {网站根域名}/web_about_index/cid/1/id/2.html > ### (1)、web:为功能模块名 > 框架配置默认模块为“web”时可以为空,详细查看系统“可配置常量” > 如:{网站根域名}/about_index/cid/1/id/2.html > ### (2)、about:为控制器 ### (3)、index:为方法名(index时可以为空) > 如:{网站根域名}/about/cid/1/id/2.html > ### (4)、cid/1/id/2 :为参数和对应的值 > 等于cid=1&id=2,比如创建了admin模块,admin模块下创建了Admin_NewsController.php,里边方法是list,访问url为:`{网站域名}/admin_news_list{伪静态后缀}` ## 4、配置文件 /config/ ### (1)、config.php >* 可以配置系统全局变量,代码中获取变量方式, > 如:`$GLOBALS['CONFIG']['sysname']` 获得的值为`ZHLPHP`, >``` >return array( > 'sysname' => 'ZHLPHP', // 列如:系统自定名称(单个变量) > 'autoload'=>array( // 自动加载类(第三方类库带文件路径的必须定义) > '/Mailer/', // 示例1 > '/uploads/', // 示例2 > ), > 'other'=>array( // 其他自定义全局变量(多级变量) > 'custom_param1' => '可继续追加其他全局变量参数……', > ), > //可继续追加…… >); >``` ### (2)、database.php >* 配置数据库链接参数,支持多数据库配置(多个数据库继续增加配置数组即可)。 >* 参数名和值必须全部小写: >``` >'mysql1'=>array( ------------------------- 数据库昵称(自定义) > 'db_type' => 'mysql', --------------- 数据库类型(mysql/oracle)可不设置默认为mysql > 'db_link' => 'mysqli', -------------- 链接方式(mysqli/pdo)可不设置默认为mysqli > 'db_host' => '127.0.0.1', ----------- 链接地址(建议设置,不设置默认为localhost) > 'db_port' => 3306, ------------------ 链接端口号(可不设置默认为3306) > 'db_name' => 'zhl_cms2', ------------ 数据库名(必须配置) > 'db_user' => 'root', ---------------- 链接帐号(建议设置不设置时默认root) > 'db_pwd' => '123456', -------------- 链接密码(建议设置不设置时默认为空无密码) > 'db_fix' => 'zhl_', ---------------- 表前缀(建议设置不设置时默认为空无表前缀) > 'db_char' => 'utf8', ---------------- 链接编码(可不设置默认为utf8) > ), >//可继续追加…… >``` ## 5、功能模块 > 如果在`app`目录下创建多个功能模块,可以自定义目录,类似上文`web`、`admin`文件夹,新建功能目录下有一般有4个文件夹分别为:`controllers`、 `serves`、 `models`、`views`,其中`controllers`必须,其他根据业务取舍。 ## 6、控制器 Controller ### (1)、新建控制器 > 在新建的功能模块下的`“controllers”`目录下新建个控制器,文件命名规则:{功能模块文件名(必须首字母大写)}+{下划线}+{自定义控制器名(首字母大写)}+{Controller.php},比如“Web_AboutController.php”。 > 注意:创建的控制器类必须继承Controller基类,如: >``` >class Web_AboutController extends Controller { > function index(){ > // 你的代码 > } >} >``` ### (2)、参数接收 > `Fun::input($name='', $val='', $type='s', $leng=0, $start=0);` > 列如:`$id = Fun::input('id');` > 列如:`$paramArr = Fun::input();` >- 参数说明: > >| __参数名__ | __参数说明__ | __备注__ | >| ------- | -------- | ---- | >| $name | 参数名 | 【选填】参数key | >| $val | 默认值 | 【选填】没有接收到值定义的默认值 | >| $type | 参数类型 | 【选填】默认s(d:数字,b:布尔型,f:小数,h:html标签,s:字符串); | >| $leng | 截取长度 | 【选填】$type为小数时代表小数点后几位; | >| $start | 开始位置 | 【选填】截取字符串时开始位置; | ### (3)、实例化调取其他控制器类 >* 示例1(同模块下实例化其他控制): >``` >// 实例化功能模块“web”下“Web_CommController”类 >$commC = new Web_CommController(); >// 调取方法 >$list = $commC->getClassLists(); >``` >* 示例2(跨模块实例化其他控制器): >``` >// 实例化功能模块“admin”下“Admin_CommController”类 >$commC = new Admin_CommController(); >// 调取方法 >$list = $commC->getClassLists(); >``` ### (4)、实例化调取服务层、数据层(可跨模块调用其他类) #### 示例1(实例化服务层): >``` >// 实例化功能模块“web”下服务器层“Web_CommServe”类 >$commSer = new Web_CommServe(); >// 调取方法 >$list = $commSer->getClassLists($id); >``` #### 示例2(实例化模型): >``` >// 实例化功能模块“web”下数据层“Web_CommModel”类 >$commM = new Web_CommModel(); >// 调取方法 >$list = $commM->getClassLists($id); >``` ### (5)、映射模版 >* `$this->display();` > 默认映射模版:{当前功能模块}/views/{当前控制器名}/{当前方法}.php;比如当前功能模块为“web”,控制为“Web_AboutController” ,方法为 "index()", 映射的模版位置为:app/web/views/web_about/index.php >* `$this->display('w_index/index');` > 指定映射模版:{当前功能模块}/views/w_index/index.php;比如当前功能模块为“web”,映射的模版位置为:app/web/views/w_index/index.php;不允许跨功能模块;只允许夸控制器和方法。 >* `$this->displays();` > 默认映射模版,但是会以“/views/common.php”为父级模版(父级模版内容也会展示)。views和子级目录下也存在common.php时比如:web/views/web_about/common.php 会重置覆盖父级的web/views/common.php 的模版内容。 >* `$this->displays('w_index/index');` > 指定映射的模版,同时先加载父级公共模版:common.php。 ### (6)、控制器变量参数映射到模版 >* `$this->set('titleName', $title);` > 把变量`$title`以`titleName`命名映射到模版,模版里接收为:`$titleName`。 ### (7)、转json数据 >* `Fun::json($list, true);` // $list转换成json并直接输出json到页面后终止; >* `Fun::json($list);` // $list转换成json但不输出(可赋值给变量); ### (8)、示例: >``` >class Web_AboutController extends Controller { > function index(){ > // 获取传过来的id值 > $aid = Fun::input('id'); > // 实例化服务层:Web_CommServe类 > $commSer = new Web_CommServe(); > // 调取Web_CommServe类下的getClassLists方法,同时传值$aid > $list = $commSer->getClassLists($aid); > // 映射值 > $this->set('list', $list); > // (也可以使用自定义Serve或者Model基类操作数据库,详细阅读文档Model使用) > $params['table'] = 'member'; > $params['field'] = '*'; // 可以指定字段如:“id,classname”等 > $params['where']['id'] = $id; > $info = Model::conn('mysql1')->find($sql); > $this->set('memberInfo', $info); > // 映射模版 > $this->display(); // 也可以用:$this->displays(); > // display和displays区别在于display直接到模版,displays包含common > } >} >``` ## 7、服务层 Serve(业务逻辑层) > 当前模块非必须,目的是为了缓解业务的复杂性和代码可维护性可以创建服务层,主要在这里写业务逻辑。 ### (1)、新建服务层 >* 在新建的功能模块下“`serves`”目录下新建业务服务,文件命名规则:{必须首字母大写功能模块文件名}+{下划线}+{首字母大写自定义服务业务名}+{Serve.php},比如“Web_AboutServe.php”。 ### (2)、业务逻辑 >* 实例化其他服务层类和数据层(可跨模块调用其他服务层/数据层),需要在当前类中操作数据库时当前类可继承Model基类也可以直接静态使用Model基类,应用实例: >``` >// 继承Model类操作数据库 >class W_CommServe extends Model { > > // 获取栏目列表(通过写业务逻辑再实例化自定义Model) > function getClassLists($id){ > // 可以写其他业务逻辑 > $id = intval($id); > if(!$id){ > return array(); > } > //实例化自定义的Model获取数据 > $where['id'] = $id; > $commM = new W_CommModel(); > return $commM->getClassLists($where); > } > > // 获取栏目列表(如果当前类继承了Model基类可以直接操作数据) > function getClassListsV2($id){ > $where['id'] = $id; > $sql['field'] = '*'; > $sql['table'] = 'classify'; > $sql['order'] = 'viewseq desc,id asc'; > $sql['where'] = $where; > $db = $this->conn('mysql1'); > return $db->select($sql); > } > >} >// 不继承Model基类操作数据库 >class W_CommServe { > > // 获取栏目列表(不管当前类有没有继承Model基类可以直接使用Model基类来操作数据库) > function getClassListsV2($id){ > $where['id'] = $id; > $sql['field'] = '*'; > $sql['table'] = 'classify'; > $sql['order'] = 'viewseq desc,id asc'; > $sql['where'] = $where; > $db = Model::conn('mysql1'); > return $db->select($sql); > } >} >``` ## 8、模型 Model(主要在这里操作数据库) > 当前模块非必须,目的是为了缓解业务的复杂性和代码可维护性可以自定义model数据层,主要在这里操作数据库。 ### (1)、新建自定义模型 >* 在新建的功能模块下“`models`”目录下新建个模型,文件命名规则:{必须首字母大写功能模块文件名}+{下划线}+{首字母大写自定义模型名}+{Model.php},比如“Web_AboutModel.php”。 >* 操作数据库时当前类可以继承Model基类也可以直接静态使用Model基类,自定义model层文件创建和数据库操作示例: >* 不管当前类是否继承Model基类都可以直接静态使用Model基类操作数据库,是否继承区别在于:继承Model类可以$this->conn('mysql1')和Model::conn('mysql1'),不继承Model类不能用$this->conn('mysql1'),只能用Model::conn('mysql1')。 >``` >// 继承Model类时示例 >class W_CommModel extends Model { > // 获取栏目列表 > function getClassLists1($where){ > $sql['field'] = '*'; > $sql['table'] = 'classify'; > $sql['order'] = 'viewseq desc,id asc'; > $sql['where'] = $where; > $db = $this->conn('mysql1'); > return $db->select($sql); > } > function getClassLists2($where){ > $sql['field'] = '*'; > $sql['table'] = 'classify'; > $sql['order'] = 'viewseq desc,id asc'; > $sql['where'] = $where; > $db = Model::conn('mysql1'); > return $db->select($sql); > } >} > >// 不继承Model类时示例 >class W_CommModel { > // 获取栏目列表 > function getClassListsV2($where){ > $sql['field'] = '*'; > $sql['table'] = 'classify'; > $sql['order'] = 'viewseq desc,id asc'; > $sql['where'] = $where; > $db = Model::conn('mysql1'); > return $db->select($sql); > } >} >``` ### (2)、数据库配置(多数据库支持) >* `$db = $this->conn('mysql1');`或者`Model::conn('mysql1');`操作时,参数`mysql1`为数据库昵称,根据数据库配置文件(自定义设置),可以自由操作不同的数据库,详细见数据库配置文件: `/config/database.php` 。 >* 如果多个数据库在同一服务器下,登录的帐号且有权访问该服务器多个数据库的权限可以跨库表连接查询, > 例如:`$sql = "select * from world.city a left join sakila.city b on a.id=b.city_id";` ### (3)、mysqli链接方式 >* `DbMySqli` 类封装了操作数据库一系列方法。 > 嫌学习过程繁琐可以直接使用query方法(支持执行原始sql): > `$db = $this->conn('mysql1');` > `$db->query($sql, $type, $returnId);` > 也可以这样写:`Model::conn('mysql1')->query($sql, $type, $returnId);` >* __注意:__ 增删改语句$type值不传,或者‘false’、0、null,' '(空),查询语句$type值传true或者1,$returnId参数默认‘id’(主键ID值,可以指定字段名) > 或者也可以放弃mysqli链接,使用下文PDO的方式,当然也可以引入自己的数据库操作类库(需要在Model基类追加数据库类)。 #### 内置mysqli链接方式快速使用示例: >``` >// 比如要操作数据库表zhl_member >// 这里填写不带表前缀的表名(database.php已经配置了可以忽略表前缀) >$table = 'member'; >// 比如数组$data是要更新的数据, >// $data数组key对应数据库字段,value对应字段的值 >$data = array( > 'uname'=>'小明', > 'qq'=>'123456789' >); >``` #### 插入-方式一(add方法) >``` > $sql['data'] = $data; > $sql['table'] = $table; > $db = Model::conn('mysql1'); > $db->add($sql); // sql执行并返回是否执行成功状态true/false > $db->rowCount(); // 受影响的行数 > $db->returnId(); // 新插入数据的主键ID值(默认id) > $db->returnId('cid'); // 新插入数据的主键值(可以指定主键字段) >``` #### 插入-方式二(addData方法) >``` > $db = Model::conn('mysql1'); > $db->addData($table, $data); > $db->addData($table, $data, 'id'); //可以指定返回新插入的主键值 > >``` #### 修改-方式一(update) >``` > $sql['data'] = $data; > $sql['table'] = $table; > $sql['where'][id] = $id; > $db = Model::conn('mysql1'); > $db->update($sql); // 执行并返回是否执行成功状态true/false > $db->rowCount(); // 返回受影响的行数 >``` #### 修改-方式二(updateData方法) >``` > $where['id'] = $id; > $db = Model::conn('mysql1'); > $db->updateData($table, $data, $where); > $db->updateData($table, $data, $where, true); //可以指定返回影响行数 >``` #### 删除-方式一(del) >``` > $sql['table'] = $table; > $sql['where']['id'] = $id; > $db = Model::conn('mysql1'); > $db->del($sql); // sql执行并返回是否执行成功状态true/false > $db->rowCount(); // 返回受影响的行数 >``` #### 删除-方式二(delData方法) >``` > $where['id'] = $id; > $db = Model::conn('mysql1'); > $db->delData('member', $where); //只关注sql是否执行成功true/false > $db->delData('member', $where, true); //可以指定返回影响行数 >``` #### 查询单条-方式一(find方法) >``` >function getInfo($id){ > $params['table'] = 'member'; > $params['field'] = '*'; // 可以指定字段如:“id,classname”等 > $params['where']['id'] = $id; > return Model::conn('mysql1')->find($params); >} >``` #### 查询单条-方式二(findData方法)第一、二参数必填,第三、四个参数选填 >``` > $info = Model::conn('mysql1')->findData($table, $where); > $info = Model::conn('mysql1')->findData($table, $where, $field, $orderby); >``` #### 查询多条-方式一(select) >``` >function getList($status){ > $params['table'] = 'member'; > $params['field'] = '*'; // 可以指定字段如:“id,classname”等 > $params['where']['status'] = $status; > return Model::conn('mysql1')->select($params); >} >``` #### 查询多条-方式二(listData方法)第一、二参数必填,第三、四五参数选填 >``` > $list = Model::conn('mysql1')->listData($table, $where, $field, $orderby, $limit); >``` #### 查询多条方法三(findAll方法) >``` >function getList($status){ > $params['table'] = 'member'; > $params['field'] = '*'; // 可以指定字段如:“id,classname”等 > $params['where']['status'] = $status; > return Model::conn('mysql1')->findAll($params); >} >``` #### 表连接查询(leftjoin、rightjoin、innerjoin 等) >``` >function getList($status){ > $sql['field'] = 'm.id,m.code,m.nickname,c.classname'; > $sql['table'] = 'member'; > $sql['as'] = 'm'; > $sql['leftjoin']['classify'] = 'c on c.id=m.class_id'; > $sql['where']['m.status'] = $status; > $result = Model::conn('mysql1')->select($sql); > return $result; >} >``` #### 执行手写sql语句方式( ` $db -> db_fix ` 可以获取表前缀,` $db -> db_config `可以获得数据库配置信息) >``` >$db = Model::conn('mysql1'); >$sql = "select * from '.$db->db_fix.'_member where id=1"; >``` __1、查询单条__ >``` >// 返回的是二维数组 >return Model::conn('mysql1')->query($sql, true); >// 返回的是一维数组 >return Model::conn('mysql1')->query($sql, true, 1); >``` __2、查询多条__ >``` >return Model::conn('mysql1')->query($sql, 1); >``` __3、添加/修改/删除__ >``` >$sql = "insert into '.$db->db_fix.'_member (classname,status) values ('zhlphp','2')"; >$sql = "update '.$db->db_fix.'_member set status='1' where id='1'"; >$sql = "delete from '.$db->db_fix.'_member where id='1'"; >return Model::conn('mysql1')->query($sql); >``` __注:转译(过滤非法字符);__ >* 可以用`$db->sqlStr($id)`进行转译/过滤非法字符 #### where条件 ##### 1、指定字段 >``` >$sql['where']['id'] = $id; >$sql['where']['level'] = 1; >$sql['where']['status'] = ['!=', 'no']; >>$sql['where']['num'] = ['>', 20]; >// 或者(注意php版本低于5.4数组用array()不要用[]): >$where = ['id'=>$id, 'level'=>1, 'status'=>['!=','no'], 'num'=>['>',20]]; >$sql['where'] = $where; >``` ##### 2、where字符串 > (不推荐,必须使用时接收参数建议进行转译,比如:`$id=$db->sqlStr($id);`) >``` >$where = " id='$id' and status='$statusCode'"; >$sql['where'] = $where; >``` ##### 3、区间查询 >``` >// (1)大于 >$sql['gt']['id'] = $id; >$sql['gt']['statusCode'] = $statusCode; >// (2)大于等于 >$sql['gts']['id'] = $id; >$sql['gts']['statusCode'] = $statusCode; >// (3)小于 >$sql['lt']['id'] = $id; >$sql['lt']['statusCode'] = $statusCode; >// (4)小于等于 >$sql['lts']['id'] = $id; >$sql['lts']['statusCode'] = $statusCode; >``` ##### 4、模糊查询 >``` >// 默认是and连接符 >$sql['locate']['classname'] = $className; >$sql['locate']['title'] = $title; >// 如果用or必须指定: >$sql['locate']['username'] = array($param,'or'); >$sql['locate']['phone'] = array($param,'or'); >// 注意:默认是and,如果用or必须指定,生成的sql相当于: >…… and locate ('是',classname) > 0 and locate ('是',title) > 0…… >…… and (locate ('是',username) > 0 or locate ('131',phone) > 0)…… >``` ##### 5、in查询(数组或者字符串) >``` >// 方式一 >$sql['in']['classname'] = array(1,2,3,4); >// 方式二 >$sql['in']['classname'] = array('1','2','a'); >// 方式三 >$sql['in']['classname'] = '1,2,a'; >// not in >$sql['notin']['classname'] = array(1,2,3,4); >``` ##### 6、or查询 >``` >// 方式一 >$sql['or']['id'] = 1; >$sql['or']['status'] = 1; >// 方式二 >$sql['or']['id'] = ['=', 1]; >$sql['or']['status'] = ['=', 1]; >$sql['or']['level'] = ['!=', 1]; >``` ##### 7、null查询 >``` >// is null >$sql['null']['title'] = 'is'; >// is not null >$sql['null']['title'] = 'not'; >``` #### order by排序 > __(1)、直接字符串__ >``` >$sql['order'] = 'a.viewseq desc,a.id desc'; >``` > __(2)、可以数组__ >``` >// 单个字段排序 >$order = array('createdate'=>'desc'); >// 或者这样写 >$order['createdate'] = 'desc'; >// 多个字段排序 >$order = array(array('createdate'=>'desc'), array('id'=>'desc')); >// 或者这样写 >$order[0]['createdate'] = 'desc'; >$order[1]['id'] = 'desc'; >// 如果php版本5.4以上也可以这样写 >$order = [['createdate'=>'desc'], ['id'=>'desc']]; >$sql['order'] = $order; >``` #### limit指定条数 >``` >// 数字方式: >$limit = 10; // 取前10条 >// 字符串方式 >$limit = '2,10'; // 第二条往后取10条 >// 数组方式 >$limit = array(2,10); // 第二条往后取10条 >$sql['limit'] = $limit; >``` #### group by分组 >``` >// 单个字段 >$sql['group'] = 'code'; >// 多个字段 >$sql['group'] = 'code,type'; >``` #### 事务 >示例: >``` >$db = $this->conn('mysql1'); // 链接数据库 >$db->startTrans(); // 开启事务 >try{ > $sql['field'] = '*'; > $sql['table'] = 'essay'; > $sql['where']['ver'] = $param['version']; > $r = $db->find($sql); // 查询数据 > if($r){ > throw new Exception("已存在"); // 存在抛出异常 > } > $sql2['data']['ver'] = $param['version']; > $sql2['data']['title'] = $param['title']; > $sql2['table'] = 'essay'; > $db->add($sql2); // 新增数据 > $db->commit(); // 提交事务 > return array('code'=>'200','msg'=>'success'); >}catch (Exception $e){ // 捕获异常 > $db->rollback(); // 事务回滚 > return array('code'=>'500','msg'=>$e->getMessage()); >} >``` #### 打印sql >在find()、select()、findAll()、update()、del() 之前$db->db_log = true;控制是否打印sql日志(日志文件目录:runtime/logs/db)日志文件格式如'DB2022_10_10.log'。 ### (4)、pdo链接方式 >* 详细参考[PHP:PDO官方文档](https://www.php.net/manual/zh/book.pdo.php?_blank)(target="_blank"),以下列举常用到的: >* 注:`$db->db_fix`可以获取表前缀。 #### - 单条: >``` >$db = $this->conn('mysql2'); // mysql2:config/database.php 配置的自定义数据库昵称 >$sql = 'select id,fid,classname,status from zhl_classify where id=:id'; >$stmt = $db->prepare($sql); >$stmt->bindValue('id', $id); >$stmt->execute(); >return $stmt->fetch(PDO::FETCH_ASSOC); >``` #### - 多条fetch改成fetchAll即可: >``` >return $stmt->fetchAll(PDO::FETCH_ASSOC); >``` #### - 添加/修改/删除: >* (只执行到$stmt->execute();后再获取响应行数): >``` >$sql = "update ……"; >$stmt = $db->prepare($sql); >$stmt->execute(); >return $stmt->rowCount() > 0; >``` #### - 获取刚插入的行数据主键ID >``` >$stmt->lastInsertId(); >``` #### - 事务 >``` >$db = $this->conn('mysql2'); >$db->beginTransaction(); // 开启一个事务 >$db->commit(); // 提交事务 >$db->rollback(); // 回滚事务 >``` >示例: >``` >try { > $pdo->beginTransaction(); // 开启一个事务 > $row = null; > $row = $pdo->exec("xxx"); // 执行第一个 SQL > if (!$row){ > throw new PDOException('提示信息或执行动作'); // 如出现异常提示信息或执行动作 > } > $row = $pdo->exec("xxx"); // 执行第二个 SQL > if (!$row){ > throw new PDOException('提示信息或执行动作'); > } > $pdo->commit(); >} catch (PDOException $e) { > $pdo->rollback(); // 执行失败,事务回滚 > exit($e->getMessage()); >} >``` ## 9、视图 View(页面模版文件) ### (1)、新建视图 >* 在新建的功能模块下“`views`”目录下新建个视图文件目录,目录命名规则:一般根据控制器名称一致(全部小写且不加Controller)例如:“`web_about`”。 >* 视图文件规则一般根据对应控制器下的方法名+.php,也可以自定义名称(自定义时控制器映射需要填写指定模版名称)。例如:`index.php`、`about.php`。 >* 公共父级模版:`common.php`(非必须)控制器调用displays方法才生效,支持自定义名称需要修改核心配置文件常量配置参数:`SYS_TMPL_PARENT` 。 >* 控制器内公共父级模版,列如:`views/web_index/common.php`会覆盖父级`views/common.php`模版。 >* /core/View.class.php文件下render方法可以引人模版引擎(如果使用可以自行扩展)。 ### (2)、获取控制器映射的值 >* 比如控制器中: >`$this->set('titleName', $title);` >`$this->set('list', $list);` > 映射过来的值,在模版中输出: >``` > > > > > zhlphp-测试页面 > > > >

>//如果是数组根据业务逻辑进行foreach遍历 >foreach($list as $v){ > echo '

'.$v.'

'; >} >// 变量插入html时可以使用定界符如(EOF可以自定义): >foreach($list as $v){ > $title = $v['title']; > echo <<
$title
>EOF; >} >?> > > >``` ### (3)、模版文件中加载其他模版文件 >* 除了控制器映射模版外,在已经映射的模版文件里再引入其他模版文件时可以参考以下操作: #### 方法一 >* 加载views文件夹下视图(注意文件后缀和系统配置保持一致) >``` > > > > > > > > >``` #### 方法二【推荐】 >* 使用辅助函数,不用关注常量,绝对路径加载更快 >``` > >``` #### 注意: >* 模版加载不能加载其他功能模块下的模版(不能跨功能模块),列如web/views下的模版不能加载admin/views下的模版。 # 四、扩展 ## 1、自定义方法 >* `/extend/Function.php` 可以自定义方法(在哪个文件使用必需引入该文件例如:`include SYS_PATH.'extend/Function.php';`)。 >* 【推荐】为了方便使用自定义方法可以在系统入口处统一引入Function.php即可,也可以在系统扩展文件service.php里统一引入Function.php,当然不仅仅是Function.php,也可以自定义其他文件用同样的方式引入即可。 ## 2、扩展第三方类库 > * 第三方类库直接放入 `/extend/` 文件夹下,类库名和文件名必须要一致(使用时直接实例化类无需引入,系统会自动引入加载实例化对应的类)。 > * 注意:如果第三方类是在extend文件下的子文件夹里或者多层子文件夹里边时,需要配置`/config/config.php`自动加载类数组参数,例如: >``` >return array( > 'autoload'=>array( // 自动加载类 > '/Mailer/mail/', // 示例1 > '/uploads/', // 示例2 > ), >); >``` ## 3、部署安全 >为了项目核心目录文件安全,可以根目录指向到`public`目录下其他目录禁止权限,但`index.php`,`.htaccess`,`web.config` 需要放到`public`目录下(index.php附件根目录SYS_PATH_FILE参数需要为空)。 >注意:这样部署的时候必须用域名访问且uploads、css、js等文件需要放到public目录下(根目录指定public目录时,本地可以虚拟域名部署)。 ## 4、全局常量 ### (1)、固定常量 > >| 常量名称 | 备注说明 | >| ------- | -------- | >| SYS_VERSION | 系统版本 | >| SYS_INIT_MEMORY | 系统初始内存 | >| SYS_INIT_TIME | 系统运行初始时间 | >| SYS_PATH | 项目根目录 | >| SYS_ROOT | 核心文件目录 | >| SYS_HOST | 项目域名路径 | >| SYS_URL | 当前访问的url | >| SYS_APP_PRO | 当前功能模块 | >| SYS_VIEW_PATH | 模版绝对路径常量 | ### (2)、可配置常量 > * 核心目录下`/helper/config.php` (常量名字固定不可修改,值可根据需求配置): > >| 常量名称 | 默认值 | 备注说明 | >| ------- | -------- | ---- | >| SYS_APP_PATH | 'app' | 应用路径 | >| SYS_APP_DEFAULT | 'web' | 指向默认模块 | >| SYS_DEBUG | false | 调试开关(系统错误是否输出到页面,生产环境请关闭) | >| SYS_DEBUG_LOG | true | 系统日志开关(系统错误是否记录日志到文件) | >| SYS_DEBUG_LOG_PATH | 'runtime/error/' | 系统错误日志目录 | >| SYS_RUN_LOG | true | 自定义日志开关 | >| SYS_RUN_LOG_PATH | 'runtime/logs/log/' | 自定义日志目录 | >| SYS_DB_LOG | true | sql日志开关 | >| SYS_DB_LOG_PATH | 'runtime/logs/db/' | sql日志目录 | >| SYS_URL_BOGUS | true | 伪静态开关 | >| SYS_URL_FIX | '.html' | 伪静态后缀初始值(必须.开头) | >| SYS_TMPL_FIX | '.php' | 视图模版文件后缀(最好不要修改) | >| SYS_TMPL_PARENT | 'common' | 视图父级模版名称(可自定义默认common) | >| SYS_PAGE404 | false | 404页面开关(SYS_DEFAULT_CLASS定义值后该参数失效) | >| SYS_DEFAULT_CLASS | '' | 类不存在默认定向指定类(设置时可覆盖404) | > ## 5、系统辅助函数 > 核心目录下`/helper/helper.php` (自定义函数可以扩展): > >| 函数 | 说明 | >| -------- | -------- | >| `SYS_SESSIONS_SET($name, $val)` | 设置sessions | >| `SYS_SESSIONS_GET($name)` | 获取sessions | >| `SYS_SESSIONS_DEL($name)` | 删除sessions | >| `SYS_SESSIONS_CLEAR()` | 清空所有session | >| `SYS_COOKIES_SET($name,$val,$expire=604800)` | 设置cookie (默认7天)| >| `SYS_COOKIES_GET($name)` | 获取cookie | >| `SYS_COOKIES_DEL($name)` | 删除cookie | >| `SYS_ERR_LOGER($str, $file='', $line='0')` | 系统错误日志打印记录(runtime/error/) | >| `SYS_LOGER($str)` | 程序打印日志文件(runtime/logs/) | >| `SYS_LOGERr($str)` | 程序日志输出到页面(美化print_r) | >| `SYS_LOGERd($str)` | 程序日志输出到页面(美化var_dump) | >| `sys_costs()` | 运行开销统计 | >| `SYS_REDIRECT($url)` | 重定向 | >| `SYS_JUMP($txt='提示', $url='')` | js提示跳转 | >| `SYS_URL_PATH($url)` | 路由自动拼接,站内跳转(如:SYS_URL_PATH('web_about_item/id/2')) | >| `SYS_TMPL($tmpl)` | 模版路径自动生成辅助(如:SYS_TMPL('w_index/test');) | >| `SYS_COOKIES_COUNT($kname, $kcount)` | 客户端操作次数限制 | >| `SYS_ENCRYPT($string, $key)` | 字符串-加密 | >| `SYS_DECRYPT($string, $key)` | 字符串-解密 | >| `SYS_ADD_PATH($path)` | 目录/路径不存在时循环创建目录 | >| `SYS_ADD_FILE($path, $data = '')` | 目录/路径不存在时循环创建目录 | > ## 6、伪静态配置 ### (1)、Apache >* 网站根目录下配置“`.htaccess`”文件,编写内容: >``` > > RewriteEngine On > > #指定目录和文件不受影响 > RewriteCond %{REQUEST_URI} !(public|uploads|job) > RewriteCond %{REQUEST_URI} !(\.css|\.js|\.png|\.jpeg|\.jpg|\.gif|\.txt|\.zip|\.rar|\.ico)$ [NC] > > # 确保请求路径不是一个文件名或目录 > RewriteCond %{REQUEST_FILENAME} !-f > RewriteCond %{REQUEST_FILENAME} !-d > > # 重定向所有请求到 index.php?zhlphpurl=PATHNAME > RewriteRule ^(.*)$ index.php?zhlphpurl=$1 [PT,L] > >``` > >* 还可以设置301重定向: >``` > #(设置301重定向) > RewriteCond %{HTTP_HOST} !^www\..+$ [NC] > RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] > #或者这样: > RewriteCond %{http_host} ^yj521.com$ > RewriteRule ^(.*)$https://www.yj521.com/$1 [R=301,L] >``` ### (2)、Nginx >* 配置“`nginx.conf`”文件,在server { 里边配置以下代码: >``` >location / { > if (!-e $request_filename) { > rewrite ^(.*)$ /index.php?zhlphpurl=$1 last; > } >} > >location ~ /\.ht { > deny all; >} >``` >使用phpstudy(小皮)时在网站根目录下配置“nginx.htaccess”文件,内容直接复制上边规则。 >注意:配置上边规则后需要重启Nginx。 ### (3)、IIS >* 配置“`web.config`”文件,编写内容: >``` > > > > > > > > > > > > > > > > > > >``` ## 7、扩展核心架构、类库、插件 > `/zhlphp/plug/` 目录下可扩展核心插件(不影响目前核心架构)。 > `/zhlphp/library/` 目录下可扩展框架核心类库(根据情况调整核心架构)。 > `/zhlphp/core/` 目录下扩展核心架构其他功能(可能会改变核心架构)。 # 五、版权信息 > Version 2.3.5 > Copyright ©遵循Apache2.0协议发布 --- --------- END --------- --- ---