插件说明

燃烧的冰2020-01-14  6.5K+

wellcms 主程序架构采用函数风格的 MVC,插件机制采用 AOP 机制,面向切面编程,也就是往代码里插入代码,合并后再执行(合并后的代码存放于 tmp 目录下),使得性能方面零损耗,不影响编译,强大而又简单。大大的简化了程序的复杂度,在同等复杂度的功能实现上比同类产品的代码简洁很多,核心只有 22 个表,非常利于二次开发。

 

wellcms程序结构

index.php 入口程序

conf/ 配置文件目录

lang/ 语言包

log/ 日志目录

tmp/ 临时目录

model/ 数据调用(复用度高)

route/ 业务逻辑(复用度低)

plugin/ 插件目录

upload/ 上传文件

view/ 模板、静态资源(js, css, img, htm, font)

xiunophp/ 公共的函数库

admin/ 后台管理

 

开发插件前 打开 index.php,修改 DEBUG 为 2 (这样可以及时看到效果,上线后还原为 0)

!defined('DEBUG') AND define('DEBUG', 2);

 

插件依赖 conf.json 文件:

{
     "name": "插件名", 
     "brief": "插件介绍",
     "version": "1.0.0", // 插件版本
     "software_version": "2.0.0",
     "type": 0,
     "installed": 0, // 0卸载 1安装
     "enable": 0, // 0禁用 1启用
     "hooks_rank": [], // 最大值优先 hook 可以同时设置多个文件优先 hook 对应的数值越大越会被优先使用
     "overwrites_rank": [], // 仅限最大值 overwrite 一次,可同时设置多个文件优先 overwrite 对应的数值越大越会被优先使用
     "dependencies": [] // 依赖其他插件
 }

 

具体开发请看 hook功能 或 overwrite

 

插件目录命名约束:开发者英文前缀 + 功能,由下划线“_”分割,比如 well_random

 

插件配置信息,统一使用

setting_set('key', 'value');
setting_get('key');
setting_delete('key');

 

插件开发数据表约束

一、表和字段命名、自定义方法、声明数组、变量、以及 css 定义class 和 id,包括表单,不管是 php 还是 js 还是 html ,命名务必使用 唯一前缀_单词(下划线"_"分割) 不要使用拼音;

well_alias 所有需要声明定义的,必须加唯一前缀,错误时方便排查,也避免冲突。

$well_arr = array('well_title' => 'This is title');
$well_title = $well_arr['well_title'];

// 定义方法
function well_thread_create($arr) {
     // .....
}

css 定义

.well_alias{}
#well_alias{}
<div class="well-text-red" id="well_order">
	HTML
</div>

<script>
	var well_data = [];
</script>

 

二、以下3个表禁止创建其他索引,如需增加索引,请在附表创建,或者新建表。创建索引前,请先灌100万数据进行测试,在 mysql 使用 explain 看是否走了创建的索引,以免创建无意义的索引。索引以左优先原则创建。

website_thread
website_data
website_comment

1.禁止使用未建索引的查询;

2.使用 int、tinyint 类型建立有效索引,尽量少使用或不使用 char 或 varchar 类型建立索引;

3.禁止在状态 status 字段上建立索引,因为在海量数据下筛选为数不多的数据,得不偿失;

4.禁止使用索引类型 UNIQUE 所有业务逻辑在程序中完成;

5.禁止在 mysql 做运算查询,如 where views>10 或 group by 之类,尽可能避免在 where 语句中使用 != 或者 <> 操作符,因为,查询引用会放弃索引进行全表扫描。实践表明高负载环境,数据库使用场景越简单越好,最好的结果就是所有查询语句除了 where 没其他;

6.禁止在非索引的字段进行查询;

7.禁止使用连表查询;

8.禁止使用非主键统计语句;

9.禁止在以下几个表建立非 tinyint 或 int 类型的字段;

website_comment_pid
website_thread_tid
website_flag_thread
website_tag_thread

10.查询、修改、删除尽可能的使用主键;

11.查询 SELECT * 不写字段,一次查完;

12.order by 必须建立在索引之上;

13.禁止使用日期类型的字段DATE\DATETIME之类,所有日期类型一律使用int,储存为时间戳或数字串如20200113;

14.字段储存尽量设计为使用tinyint或int,能用tinyint就不用int,能用int就不用bigint。能用tinyint代替char和varchar就代替,比如很多人喜欢直接用“男”“女”储存性别,可以直接用tinyint(1),储存值0无性别 1男 2女 这种形式;

15.创建字段默认值禁止使用“无”或 “NULL”,数字型字段一律默认值0,字符类型一律空。

16.很少使用的大字段拆分到单独表,如wellcms的内容详情,使用单独的data表,因为,绝大部分的操作都以标题为主;

17.封装 SQL 语句不能任性写,必须依照现有的索引左优先原则,创建索引前请设计好,不能 where `uid`='1' and `tid`=`1` 然后高兴就又写成 where `tid`=`1` and `uid`='1' 如果你这样玩,我会喷到你体无完肤。索引是什么顺序,语句必须保持一致。

18.所有内容主题类的请求数据,一律查询主键后扔进官方统一拉取数据的函数,统一获取数据,避免多次查询同一个表,wellcms 所有的操作,只对同一个表查询一次,不管有什么花样的数据调用,任何页面的数据,每个表只能查询一次,这是原则,不能改变。wellcms 不管是门户模式,还是扁平模式,所有表只查询一次。因为 wellcms 是专为大数据量、高并发网站设计的架构。同一个页面查询同一个表 N 次,还谈什么数据承载量和高并发,这就是笑话。

<1>列表类统一拉取,避免多次查询thread表 thread_unified_pull($arr) 具体二开请自行查看该函数如何使用;

<2>详情页其他主题调用,集合tid统一拉取数据 thread_other_pull($thread) 具体二开请自行查看该函数如何使用;

19.单一查询适当使用 cache ,用户类数据一律永久缓存,标题类一律缓存生命期7200秒,内容详情类一律缓存生命期3600秒或1800秒,更新数据记得清理缓存cache_delete 或者直接 cache_update 更新缓存数据(具体使用请查看相关函数),避免再次到SQL获取,对于一直动态变化的数据没必要使用缓存,如列表。

20.不要问为什么,听话照做,不进坑。

 

字段类型使用约束

尽可能的使用 tinyint 或 int

 

hook 代码的 php 文件 ( 仅限于 php 文件 ),请使用下面的方式,开头必须加上 exit; 目的是以防文件运行,影响安全。

例如 index_inc.php 这个文件有个 index_inc_after.php 钩子,那么,hook这个地方的文件命名 index_inc_after.php 代码如下

<?php exit;
$route = param(0, 'list'); /* 其他业务代码 */
?>

 

htm 文件加载css和js文件,插件全部采用异步加载:

异步加载 js, 加载成功以后 callback

$.require(... callback)

...: js 文件的URL
callback: 最后一个参数为回调函数

<script type="text/javascript">
    var well_js_path = '<?php echo $conf['path'];?>';
    $.require(well_js_path+'1.js', well_js_path+'2.js', function() {
        alert('after all loaded');
    });
</script>

无需回调的直接加载

<script type="text/javascript">
    $.require('<?php echo $conf['path'];?>plugin/huux_tinymce/prism/prism.js');
</script>

异步加载 css

<script type="text/javascript">
    var well_js_path = '<?php echo $conf['path'];?>';
    $.require(well_js_path+'1.css');
</script>

 

0