😍 入门指南


>i 本文档的最新修订日期是: > **2021-08-28** # 前言 ## 版本说明 当前文档对应的框架版本是 `5.1.0` 。 在 `5.x` 中,我们进行了大范围的调整,因此与 `4.x` 版本不兼容。如果您正在使用更低版本,请参看 **`升级`** 章节中的内容。 ## 综述 感谢您了解84PHP开源框架! >d 请注意,一定不要以使用 `MVC` 模式开发框架的使用经验来理解84PHP。 此框架是一款力求在 `性能指标``简洁度` 之间达到平衡的开发框架,同时尽可能的在减少开发者使用框架时所花费的时间,为此我们引入了诸多新颖的设计理念: * 高内聚的可插拔模块设计 * 简洁的文件结构 * 快捷传参 * 完善详细的报错信息 在5.X版本中,我们更侧重于提升编码体验和提高开发效率,因此进行了大量调整。 ## 运行环境 运行环境为 `PHP7+` 。 ## 性能&安全性 84PHP已对常见的安全问题,实现了相应的安全防护。 另一方面,我们始终认为“代码量是运行效率的重要标准”,虽然代码量少不一定意味着运行效率就高,但臃肿的代码一定是运行效率低的。 因此,在每一个模块的编写过程中,我们尽量保证代码紧凑。 ## 交流方式 >i 84PHP官方QQ群:823907259 ## 样例 我们提供了一个简单的留言板系统 `Demo` 作为示例,帮助初学者入门以及深入理解本框架。 Demo下载地址:[点击进入>>>](http://down.84php.com/84php-5.1.0-demo.zip) # 目录结构 ``` / 站点根目录(或虚拟主机中的 www & wwwroot 目录) │ ├─Config 配置文件目录 │ ├─Common.php 核心配置文件 │ ├─ErrorHtmlStyle.php 用于浏览器展示的报错页模板 │ ├─ErrorJsonStyle.php Json格式的报错页模板 │ └─... 其它模块配置文件 │ ├─Core 应用目录 │ ├─Class 模块目录 │ │ └─index.php 默认文件 │ │ │ ├─Errors 报错定义目录 │ │ ├─Http404.php Http404状态码报错文件 │ │ ├─Http500.php Http500状态码报错文件 │ │ ├─Http4xx.php Http4xx状态码报错文件 │ │ ├─Http5xx.php Http5xx状态码报错文件 │ │ └─index.php 默认文件 │ │ │ ├─Initial.php 初始化文件(请勿修改) │ └─index.php 默认文件 │ ├─Lib 库文件目录 │ ├─Rewrite 伪静态规则目录 │ ├─Source 模板目录 │ ├─Data 数据处理部分 │ └─Template 静态模板部分 │ ├─Temp 模板目录 │ ├─Cache 编译缓存目录 │ ├─Data 数据缓存目录 │ ├─Log 日志文件目录 │ ├─ip-blacklist.php IP黑名单 │ └─ip-whitelist.php IP白名单 │ ├─Web Web目录(对外访问目录) │ └─index.php 入口文件 │ └─Readme.html 文档链接 ``` # 准备工作及核心配置 ## 准备工作 >w 在开始使用前,需要通过服务器的伪静态设置将所有流量牵引至 `/Web/index.php` 文件。 `/Rewrite` 下包含了伪静态规则,可根据需要自行调整。 请根据具体情况选择 `develop-开发环境版本` (不屏蔽报错)或 `product-生产环境版本` (屏蔽报错)的伪静态规则。 * IIS环境下,请将对应环境版本文件夹内的 `web.config` 文件放置于网站根目录,在安装好URL重写模块之后即可使用。 * Apache环境下,请将对应环境版本文件夹内的 `.htaccess` 文件放置于网站根目录,在Apache的配置文件中开启URL重写选项之后即可使用。 * Nginx环境下,请将对应环境版本文件夹内的 `84php.conf` 文件引入到Nginx的配置文件 `nginx.conf` 中,也可以将84php.conf中的代码插入到nginx.conf中的合适位置。 * 如果有额外需求,可根据需要自行调整伪静态规则。 >i 规则隐藏了.php文件后缀,并屏蔽了对/Core、/Lib、/Source、/Temp等关键路径的访问,以及当HTTP状态码为4xx或5xx时,展示友好的出错页面。同时将流量牵引至/Web/index.php。 ## 核心配置 >w 框架的核心配置文件位于 `/Config/Common.php` ,文件中的 `$FrameworkConfig` 数组变量,包含了所有的关键设置。 * **`Debug`** `(Bool)` `TRUE` : 调试模式,`TRUE` 代表开启、`FALSE` 代表关闭,默认开启。 当调试模式关闭时,报错等级将调整至最低 `(意味着某些不重要的错误将会被忽略)` ,而当调试模式开启时,框架会自动对修改过的模板文件进行编译,并告知浏览器对所有页面都不进行缓存;同时在发生错误时显示详细的报错信息 `(可能包含文件路径、出错类型或数据库信息)` 。 在调试模式关闭的情况下,可以开启 `Wrong` 模块中记录日志的配置项,报错信息将会被写入日志中,详情请参阅该模块的说明文档。 >d 为了确保安全,在正式使用(以下称作生产环境)时,务必关闭调试模式。 * **`Route`** `(String)` `'MIX'` : 框架的路由模式。 当值为 `BASE` 时,可通过类似 `/Web/index.php?p_a_t_h=/auth/login` 的形式,即通过参数 `p_a_t_h` 访问缓存,必须以 `/` 开头,且不含后缀 `.php` 。 当值为 `PATH` 时,可通过类似 `/auth/login` 的形式直接访问。 当值为 `MIX` 时,则同时兼容上述两种方式。 >w 是否区分大小写,取决于服务器环境配置。 * **`Https`** `(Bool)` `FALSE` : 是否强制使用HTTPS访问,`TRUE` 代表开启、`FALSE` 代表关闭,默认关闭。 如果开启,将会把HTTP请求重定向为HTTPS请求。 >w 由于运行环境的限制,在某些情况下(如服务器环境配置不当时),如果不存在 `$_SERVER['HTTPS']` 变量,将导致框架 `报错` 。 * **`RunTimeLimit`** `(Bool | Int)` `FALSE` : 程序运行时的超时时限,单位为秒,默认跟随运行环境配置。 当此变量为 `Bool` 类型的值 `FALSE` 时,将 `跟随` 运行环境配置;此变量为 `Int` 类型时,请参考PHP官方手册中有关 `set_time_limit()` 函数的说明。 >w 由于运行环境的限制,在某些情况下(如在虚拟主机中运行),本设置可能 `不会生效` 。 * **`SafeCode`** `(String)` `''` : 安全码,默认为空。 请将此项设置为一个长度 `大于10` 的随机字符串,否则所有使用到安全码的功能 `都不会` 启用。 * **`SessionStart`** `(Bool)` `FALSE` : 用以指定是否自动地开启SESSION,`TRUE` 代表开启、`FALSE` 代表关闭,默认开启。 如果想要在应用运行时 `自动地` 启用SESSION,请将值设置为 `TRUE` 。 * **`TimeZone`** `(String)` `'Asia/Shanghai'` : 程序运行时的时区,默认为中国上海。 请参考PHP官方手册中关于 `date_default_timezone_set()` 函数的说明。 >w 由于运行环境的限制,在某些情况下(如在虚拟主机中运行),本设置可能 `不会生效` 。 * **`Always200`** `(Bool)` `TRUE` : 用以指定是否在Hrader中始终返回 `HTTP 200` 状态码,`TRUE` 代表开启、`FALSE` 代表关闭,默认开启。 开启后,无论什么情况发生,框架都将尽可能地返回 `HTTP 200` 状态码。 # 常量 截至当前版本,本框架有以下常量: * **`FrameworkVersion`** `(String)` `~` : 此常量代表了框架版本号。 * **`RootPath`** `(String)` `~` : 此常量代表了站点根目录,即 `/Core` 目录的父一级目录路径。 * **`Runtime`** `(Float)` `~` : 此常量代表了框架开始加载时的时间戳。 * **`IntRuntime`** `(Int)` `~` : 此常量代表了框架开始加载时的Int型时间戳。 * **`URI`** `(String)` `~` : 此常量代表了访问请求的URI。 # 模块 在路径 `/Core/Class` 中,包含了框架所有使用到的 `类`(Class,每一个类均拥有各自的一类功能)。 但在我们所有关于84PHP的表述中,将把它称作 `模块` : 框架源码包中已经包含了大部分常用模块,您可以自行编写模块,还可以下载其他开发者编写的 `第三方模块` 。 在路径 `/Config` 中,可能存在与模块名相对应的 `配置文件`(也可能不存在)。 例如,`Pay.php` 对应的是 `Pay` 模块(提供在线支付功能),其内存储着支付接口的通信密钥和该模块所需的其它配置项。 >w 您可以通过手动编辑配置文件的方式调整配置项,亦可通过Setting模块进行灵活的配置,有关Setting模块的详细说明,请参阅该模块的说明文档。 有关模块配置项的动态注入,请查看下一节内容。 # 动态注入配置项 动态注入配置项,请通过Setting模块中的Change()方法完成。有关Setting模块的详细说明,请参阅该模块的说明文档。 通过 `动态注入` 定义与通过 `配置文件` 定义的区别: * `动态注入` 更加灵活,适合需要使用多个同类配置项的情况,但由于通常要从外部获取变量的值(比如从数据库中读取),效率会低于从配置文件中直接获取。因此特别是在并发量大的时候,性能差异会更加明显。 * `配置文件` 性能更优秀,并且不会因为数据库泄露等未知因素失去配置,但灵活性稍差,建议在高并发场景使用。 >d 动态注入的配置项仅 `运行时` 有效。 # 语法 本框架中有两种语法,一种是 `模块语法` ,另一种是 `模板语法` 。 * `模块语法` ,就是调用模块时使用的语法,它们应当出现在 `Data` 目录中的模板文件里,完成模块对应的功能。 语法如下: **模块名 :: 方法名 ( 传参数组 )** **在详述之前,请先看一个例子。** 如果在模板文件中使用模块语法: **\$abc= Db :: Select ( \$Config ) ;** 那么,将会调用 `Db` 模块中的 `Select()` 方法,将参数 `$Config` 传入其中,随后在数据库中查询数据,并将结果存储在 `$abc` 变量中。 **回过头看模块语法:** **模块名 :: 方法名 ( 传参数组 )** 例如,在 `Vcode` 模块中使用 `Base()` 方法生成一个验证码,由于在Vcode模块中Base()方法是没有返回值的(也不需要获取返回值),那么: **Vcode :: Base ()** 就可以完成方法的使用。 自4.0.0版本起,方法传参的方式调整为快捷传参,即通过数组 `array('参数名'=>[参数值])` 的方式进行传参。详情见各模块示例代码。 >w 传参数组中的键,即 `参数名` 还可以用 `中文参数名` 代替。 例如 `array('字段'=>'id')` 等同于 `array('field'=>'id')` ,增加代码可读性的同时减少记忆负担。 详情见各模块方法的参数说明。 * `模板语法` ,就是静态模板中的快捷语法,以HTML内嵌代码的形式实现PHP语言中的 `echo``if...else...``foreach` 等功能,并且可以嵌套结合使用。 它们应当出现在 `Template` 目录中的模板文件里。 和大多数框架类似,模板语法如下: 1. **输出变量**: ``` {变量} ``` 例如, ``` {$Var} ``` 等同于: ```php ``` 2. **if...else / if...else...语句**: ``` {if (条件)} [code] {else if (条件)} [code] {else} [code] {/if} ``` 例如, ``` {if ($Var==1) } Yes{$Var}. {else if ($Var==2) } Lucky{$Var}. {else} No. {/if} ``` 等同于: ```php Yes. Lucky. No. ``` 3. **Foreach(或loop)语句,其中数组元素的键为** `$Key` **,对应的值为** `$Val` : ``` {foreach 变量} [code] {/foreach} ``` 例如, ``` {foreach $Array } The key is {$Key}, and the value is {$Val}. {/foreach} ``` 等同于: ```php $Val){ ?> The key is , and the value is . ``` 4. **运行一段PHP代码**: ``` {? PHP代码 ?} ``` 例如, ``` {? echo 'Now timestamp is:'.time(); ?} ``` 等同于: ```php ``` >w 模板语法的语法规则存储于 `/Config/Cache.php` ,您可以自行设计语法。 # 模板 > 自4.0.0版本起,已删除原 `/Source/Action` 目录。如需升级,将其中的文件移动到 `/Source/Data` 目录下即可。 框架模板文件的默认路径是 `/Source` ,包含 `Data``Template` 两个目录。 浏览器访问时,在没有设置额外伪静态规则的情况下,Web目录下会有与之对应对应的实体文件。即访问 `yourdomain.com/a/test` 时,在 `/Temp/Cache` 目录下,目录 `a` 以及目录a中的 `test.php` 是真实存在的,而这些文件就是经过编译处理之后的文件。 * `Data` 目录,是数据模板存放的目录,存放的是操作数据的PHP代码文件。 * `Template` 目录,是静态模板存放的目录,一般来说尽可能的少包含原生PHP代码,以便提高模板的移植性。 **两者之间的关系是:** 1. 假设 `Template` 目录有一个文件 `A.php` ,并且只是一个 `没有数据操作` 的页面,比如,仅仅是从SESSION中输出用户名 ``` {$_SESSION['username']} ``` ,而没有比如查询数据库这一类需要用到模块的复杂操作,则只需要建立 `Template/A.php` 即可,框架按照模板语法编译后将会在 `/Temp/Cache` 目录下生成 `A. php` 。 2. 假设 `Template` 目录中有文件 `B.php` 需要展示用户当前的余额$Count,而余额$Count `需要从数据库中查找最新数据` ,那么, 需要在Data目录下建立一个 `相同名称` 的文件,即建立 `Data/B.php` ,并在其中编写例如: ``` $Config = array( 'wherefield'=>'id', 'wherevalue'=>'3', 'wherefield'=>'=', ); $Count=Mysql :: Select($Config); ``` 的代码并保存,然后建立 `Template/B.php` ,并在其中编写例如(假设余额存储在数据表字段 `total` 中): ``` {$Count['total']} ``` 的代码并保存,框架会将 `Data/B.php` 中出现的 `模块语法` 编译(编译完成的部分称作 `PartD` )、将 `Template/B.php` 按照 `模板语法` 编译(编译完成的部分称作 `PartT` ),随后框架将按照 `PartD` 在前、`PartT` 在后的规则,将这两部分编译后代码合并,最终在框架 `/Temp/Cache` 目录下生成 `B. php` 。 本示例编译后的 `B.php` 代码如下(已省略无关的代码): ```php 'id', 'wherevalue'=>'3', 'wherefield'=>'=', ); $Count=Mysql::Select($Config); echo $Count['total']; ?> ``` **当仅仅需要操作数据,而不进行大量HTML输出时,比如判断用户是否登陆的代码,可以仅在 `Data` 目录下建立模板。** **下面是两者的关系图:** ![structure.png](https://img.cdn.bux.cn/open/84php/3.0.1/structure.png) >w `Data``Template` 目录中模板文件的路径要保持相同。 如 `Template/Test/A.php` 对应的文件是 `Data/Test/A.php` 。 模板文件相对于模板目录( `Data``Template` )的路径,也就是编译后文件相对于 `/Temp/Cache` 目录的路径。 # 缓存及自动编译 在 `/Temp/Cache` 下的所有文件均为经过编译的 `缓存文件` 。 框架具有自动编译机制,如果存在 `尚未编译` 的模板文件,或存在模板文件的 `修改时间` 晚于缓存文件的修改时间且已经过了缓存有效期,则框架会对该模板自动进行编译。 >d 切勿直接修改缓存文件!超过缓存有效期后,被修改的缓存文件将被回滚。 如遇此类情况,请删除 `/Cache` 目录下的对应文件进行缓存重建。 >w 框架具有无效缓存清空机制,如果不存在缓存所对应的模板文件,则会 `清除` 对应的缓存。 即当您删除某个模板文件后,对应的缓存并不会立即被清空。只有在该缓存被请求时,才会清除缓存,且该缓存不会被输出。 >w 当服务器调整系统时间后,或服务器时间异常时,可能会导致自动编译 `失效` 。框架会自动重置模板文件的修改时间来修复这个问题。如果仍然无法解决,请调整服务器时间,并清空 `/Temp/Cache` 目录下的所有文件,或者使用 `Cache` 模块重建缓存(详情见模块说明)。 >w 如果您的模板文件存在语法错误,例如出现两个;;符号,将会触发php系统级别的报错,且报错将会发生在自动编译模块运行之前。 遇到这样的情况,您可以在修改完模板文件中的错误代码之后,重新访问页面。 # 文件引入&使用库 在实际场景中往往需要使用 `require``include` 引入一些常用的文件,但由于框架的编译机制为被动触发编译,因此对于引入的文件,无法自动触发编译。且Source目录下的模板文件经编译后能够被访问者访问,这与本框架提倡的高安全性严重背离。 另一方面,在项目实践中,常常需要使用来自第三方的库文件,例如用PHP生成二维码或用PHP解压缩文件,在以往的版本中只能将库文件放在 `/Core/Class` 目录中,既不方便维护,也不方便升级迭代。 自5.0版本开始,可将上述文件放在 `/Lib` 目录下,该目录 `不能` 通过Web访问。 框架已内置Lib目录的路径,如果需要引入Lib目录下的 `test.php` ,可通过如下方式引入: * 快速引入: `require('test.php');` * 通过物理路径: `require(RootPath.'/Lib/test.php');` # 路由 框架的URI组成就是最原始的 `域名/文件相对路径` 模式。 其中 `文件相对路径` 指的是缓存文件相对于缓存目录的路径,同时也是模板文件相对于模板目录( `Data``Template` )的路径。 当访问时将首先在Web目录下寻找对应的文件,如果有则停止后续操作,因此如果有文件 `/Web/css/style.css` ,则直接访问 `域名/css/style.css` 即可。 上面这一步由服务器的伪静态规则完成,接下来的步骤将由框架完成。 当此路径是一个目录时,会优先寻找缓存目录中此路径下的 `index.php` ,等同于访问 `相对路径/index` 。 因此尽量不要把文件夹命名为 `index` ,因为会触发下一节将讲到的 `重名策略` 。 若未找到文件,将会尝试在缓存目录中的 `文件相对路径.php` 文件。 当找不到任何文件时,将触发报错。 >w 我们强烈建议页面使用 `原生URI` 形式,即 `?Field1=value1&...` 这样的形式传递参数,因为目前的搜索引擎已经能够解析URI参数而不影响SEO,且用户记忆URI中的参数的场景极少。 如果您依然需要对URI进行美化,请通过服务器的伪静态功能中的正则表达式完成操作,即使如此,服务器的操作效率通常比PHP高出20%以上。 # 通过命令行运行 在某些情况下(比如通过服务器执行定时任务时),就需要用命令行来执行代码。执行的页面为 `/Web/index.php` ,参数名为 `path` ,参数值为以 `/` 开头的 `页面的URI` : 假设有一个页面,访问 `aaa.com/api/refresh` 时能使其工作,那么通过命令行执行它时,可执行以下命令: ## linux ``` [root@user]# /usr/local/php/bin/php /data/84php/Web/index.php --path /api/refresh ``` ## windows ``` D:\php\php.exe D:\data\84php\Web\index.php --path /api/refresh ``` >w 上述命令中,php的程序路径、入口文件的路径和执行页面的URI,都需要根据服务器的实际环境进行修改。 # 重名策略 由于框架使用实体文件对应的缓存方式,因此对于文件名与目录名 `重名` 时采用了特定的处理策略。 如果存在 `a.php` ,且同级目录下存在文件 `a/index.php` ,即如下文件结构: ``` /Temp/Cache 缓存目录 ├─a │ └─index.php └─a.php ``` 当访问 `xxx.com/a` 时,运行的是 `a.php` 而非 `a/index.php` ,如果需要运行后者,请访问 `xxx.com/a/index` 。 缓存的编译/更新同样遵循上述策略。 # 报错机制 框架拥有完善的报错机制,报错信息页的模板位于 `/Config/ErrorHtmlStyle.php``/Config/ErrorJsonStyle.php` 中,您可以自行替换,其中 `{$ErrorInfo}` 为报错信息显示的位置,`{$Code}` 为状态码,`{$Version}` 为框架版本号。 对于部分模块,当调试模式 `开启` 时,将会显示详细的报错信息和文件的路径、出错行号,否则将显示基本的错误码。错误码对应的详细错误信息,请在文档 `错误码查询` 中了解。 如需仅展示 `JSON``HTML` 形式的报错信息,请在 `Wrong` 模块的配置文件进行配置。 >d 由于PHP语言的限制,有少数在代码运行前的报错无法被捕获。此部分报错将由 `PHP系统` 完成。 详情请参见 `Wrong` 模块说明文档。 # 安全规范 **养成良好的编码习惯对于应用安全性的提升至关重要!** 以下是我们推荐的安全规范: * 必须对 `所有` 来自外部的输入进行合法性校验!不建议直接输出用户上传的非二进制文件的内容; * 尽可能的使用服务器端会话管理 `而非` COOKIE来实现用户的登录状态保持; * 在生产环境下,务必 `关闭` 调试模式; * 尽量 `不要` 将用户输入的内容作为SQL语句中的字段操作。也就是说,如果需要操作由用户确定的字段,则应尽可能的预先定义好字段,通过数字编号代替。否则,请单独建立数据库,并建立限制权限的单独的数据库用户; * 请通过服务器端的伪静态设置,将非 `/Web` 目录以外的目录设置为禁止访问; * 请设置对应的HTTP403、404、500页面,而 `不显示` 服务器默认的错误页面; * 请特别关注 `HTTP403` 列出目录的安全隐患; * 请使用CDN/WAF完成服务器原始IP地址的隐藏及安全防护,同时建议在服务器上安装安全防护软件; * 关闭生产服务器服务器的 `21/22/3389` 端口; * 对用户上传目录取消执行权限; * 启用HTTPS。 # 高性能 以下是我们推荐的高性能架构规范: * 开启OPCache; * 尽可能地使用CDN,以降低源站 `带宽消耗` ; * 条件允许的话, `站库分离` 也是提升性能的好方法; * 不要在数据库SQL语句中进行多表联合查询或嵌套查询; * 尽可能地将计算过程交由 `代码层` 执行,而非数据库; * 尽可能地避免调用远程API; * 对于网站应用,强烈推荐使用静态页+AJAX的方式进行构建; * 条件允许的话,使用对象存储或专门的存储服务器来接收上传的文件; * 将过于久远的数据转存到单独的数据库或者文本中。 # 版权声明&联系方式 > 本框架为免费开源、遵循Apache2开源协议的框架,但不得删除框架内文件的版权信息,违者必究。 > > This framework is free and open source, following the framework of Apache2 open source protocol, but the copyright information of files are not allowed to be deleted,violators will be prosecuted to the maximum extent possible. > > ©2021 Bux. All rights reserved. >w反馈Bug,可加入 `QQ群` 或发送邮件至 `tech@bux.cn` 进行反馈。