插件开发文档:模块开发

创建自定义内容模块

基于宸逸CMS框架的全新模块设计,方便开发者快速二次开发

什么是内容模块?

内容模块是cms核心部分,比如文章、新闻、下载、商品、物品、货物、书籍、图片等等功能,
内容数据由内容主表、内容附表、栏目模型主表、栏目模型表附表构成,主表存放内容公共拥有的信息,
比如标题,添加时间,点击量等,内容附加表存放内容信息,比如普通文章内容、商品信息、软件信息等。

哪种场景下需要创建模块?

对数据量规划超过百万以上,那么很有必要创建多个模块来分表储存,减少查询负担;

传统站、资讯博客站、企业站,就没必要创建多个模块了。


操作方法:

第一步、开启开发者模式

第二步、进入创建模块位置

创建自定义内容模块


第三步、给模块命名

模块名称:给他取个名字

模块目录:英文字母,不能有空格和其他符号,不得出现数字

模块图标:后台的显示图标,方便查找

文件权限:需要对创建目录有写入权限,否则文件会写入失败


第四步、创建成功

这时候系统会自动根据你的参数来生成一个全新的模块,你可以通过自定义字段和模块表单来扩展更多的功能。


第四步、安装模块

进入模块管理界面,进行安装模块

image.png

重写内容Content类

Content类用于对模块内容数据的操纵,开发者可以对其进行重写继承,以便适用于自己项目的二次开发。


我们以Demo模块为例,新建App/Demo/Models/Content.php

category($module, $data, $page);
    }
    
    // 格式化首页seo信息
    public function _format_home_seo($module) {
        return \Phpcmf\Service::L('Seo')->module($module);
    }
    
    // 格式化内容页seo信息
    public function _format_show_seo($module, $data, $page) {
        return \Phpcmf\Service::L('Seo')->show($module, $data, $page);
    }
    
    // 格式化内容搜索seo信息
    public function _format_search_seo($module, $catid, $params, $page) {
        return \Phpcmf\Service::L('Seo')->search($module, $catid, $params, $page);
    }
}


目前提供以上的可重写方法体,开发者可以自由定义

重写搜索Search类

Search类用于对模块内容的搜索,开发者可以对其进行重写继承,以便适用于自己项目的二次开发。


我们以Demo模块为例,新建App/Demo/Models/Search.php

 '对应的sql语句',多维数组
        // if (isset($where['title'])) { $where['title'] = '新的sql语句'; }
    
        // 比如我加一个条件作为搜索条件
        // $where['zt'] = "zt=1"; // 表加一个zt字段=1的数据
        return $where;
    }
}


目前提供以上的可重写方法体,开发者可以自由定义

模块Config配置规则

模块信息文件:Config/App.php

 'module',
    'name' => '商品', //名称
    'icon' => 'fa fa-square', //图标
    'system' => '1', //1默认标准模块,出现在内容菜单下 2菜单不出现在内容下,由开发者自定义    
    'mtype' => '1', //2表示只能安装独立模块,1表示安装共享,0为不限制
    'hlist' => '0', //1表示不出现在模块管理、评论tab、搜索tab、内容维护tab的列表之中
    'hcategory' => '0', //1表示不使用栏目功能和发布权限功能
    
];


安装时的SQL文件:Config/Install.sql

DROP TABLE IF EXISTS `{tablename}_test`;
CREATE TABLE IF NOT EXISTS `{dbprefix}_test` (
  `id` BIGINT(18) unsigned NOT NULL AUTO_INCREMENT,
  `time` int(10) NOT NULL
  PRIMARY KEY (`id`),
  KEY `time` (`time`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='test';

一般用于创建表,{tablename}表示模块表的前缀,例如dr_1_news,那么常用变量有:

{moduleid} 模块安装后的id
{dbprefix} 数据表前缀
{tablename} 模块表前缀
{dirname} 模块目录名称
{siteid} 当前站点id


卸载时的SQL文件:Config/Uninstall.sql

于安装相反,这里写删除表的语句吧


安装后运行的程序代码:Config/Install.php


安装后运行的程序代码:Config/Init.php


内容表结构配置:Config/Content.php

此文件有系统生成不建议修改


模块表单配置文件:Config/Form.php

安装模块时自动创建模块表单


模块目录结构

模块目录结构如下:

```
├─App/ModuleName/ 		            -- 模块目录名称
│   ├─Config/ 			    -- 相关配置文件
│   ├─Controllers/ 			-- 控制器
│   │   ├─Admin/ 			-- 后台操作控制器
│   │   ├─Member/ 			-- 用户中心控制器
│   ├─Models/ 			    -- 数据库模型[可选]
│   ├─Views/ 			    -- 后台html文件
│   ├─Librarys/ 			-- 类库[可选]
│   └─Helpers/ 				-- 函数库[可选]
└─ ...
```


内容变更栏目联动继承类

当栏目变化时系统会联动变化默认的一些相关表,在二次开发时如果涉及到了栏目的自定义表需要重写conten类

http://help.xunruicms.com/461.html


内容变更栏目联动继承类方法

// 变更栏目时的联动继承类
protected function _edit_category_row($row, $catid) {

}

$row 是当前内容主表的记录,其中$row['catid']是未变之前的栏目id号

$catid 是新的栏目id号

内容变更作者联动继承类方法

当内容发布者变化时系统会联动变化默认的一些相关表,在二次开发时如果涉及到了栏目的自定义表需要重写conten类

http://help.xunruicms.com/461.html


内容变更作者联动继承类方法

// 作者时的联动继承类
protected function _edit_author_row($row) {

}

$row 是当前已变更后的内容主表的记录,其中$row['uid']是已经变更之后的用户id号



内容页面的格式化显示内容

当需要改变模块内容中的某些字段或者联动加一些相关数据时,就需要格式化显示内容,这个内容只用于模块内容的显示页面,show.html页面


重写conten类

http://help.xunruicms.com/461.html


内容页面的格式化显示内容继承类方法

// 格式化处理内容
public function _format_content_data($data) {
    return $data;
}

$data 是当前模块内容的全部记录

你自己增加内容就往本数组进行赋值,自带缓存功能!


内容继承类方法

// 格式化显示内容
public function _format_content_data($data) {
    
    $data['xxxx'] = '这是我的增加变量';
    return $data;
}

$data 是当前内容show.html输出的全部字段


那么,show.html可以读取变量xxxx

{$xxxx}



内容审核之后的回调处理

当内容被后台管理员审核通过或者审核被拒绝时的回调


需要重写conten类

http://help.xunruicms.com/461.html


内容变更作者联动继承类方法

// 内容审核操作之后
public function _call_verify($data, $verify) {
    
    if ($data['status'] == 9) {
        // 审核通过了并发布状态
    } elseif ($data['status'] == 0) {
        // 被拒绝审核
    } else {
        // 审核通过了,并进入下一个审核阶段
    }
    
    if ($verify['isnew']) {
        // 这是新增的审核内容
    } else {
        /// 这是修改已有的内容
    }
}

$data 是当前已变更后的内容主表的记录

$verify 是审核表的记录



用户中心模块控制器继承重写

用户中心模块控制器的父类文件:

dayrui\App\Module\Control\Member\Module.php 此控制器继承于Table类

此控制器作用是用于用户中心对模块的操作控制。


我们以Demo模块的用户中心模块控制器为例:

dayrui/App/Demo/Controllers/Member/Home.php

其文件内容如下:

_Member_List(true);
        return \Phpcmf\Service::V()->display($tpl);
    }

    public function add() {
        $tpl = $this->_Member_Add(true);
        return \Phpcmf\Service::V()->display($tpl);
    }

    public function edit() {
        $tpl = $this->_Member_Edit(true);
        return \Phpcmf\Service::V()->display($tpl);
    }

    public function del() {
        $this->_Member_Del();
    }
}


用于内容模块的管理、添加、修改、删除动作的控制


如何继承修改父类的方法内容呢?因为父类控制器继承了Table类,那么子控制器也具备table类的继承属性




模块属性参数配置

每个模块都可以定义一种个性配置,为模块属性增加各种配置选项


例如,为deomo模块增加文本选项appid参数设置


1、新建dayrui/App/Demo/Controllers/Admin/Param.php

_Module_Param();
   }

}


2、新建模板dayrui/App/Demo/Views/param.html

{template "header.html"}


    

{dr_lang('更改数据之后需要更新缓存之后才能生效')}

    {$form}                                                                   {dr_lang('参数设置')}                                        
                                                           AppId                                                                                                                          AppSecret                                                                                                                                            {dr_lang('保存')}               {template "footer.html"}


3、预览地址:admin.php?s=demo&c=param&m=index

image

4、读取这些参数的方式

A、程序中读取:

当前模块中时: $this->module['setting']['param']['字段名']

B、模板中读取:

当前模块中时: {$ci->module['setting']['param']['字段名']} (文本类型字段)

全局模板读取:

{php $mp=dr_module_param("模块目录", "字段名");}
输出{$mp}

其他字段如何输出?

1、首先输出这句话:

{php $mp=dr_module_param("模块目录", "字段名");}

2、接下来生成代码:

https://www.xunruicms.com/doc/code/field.html

类别选择:(在自定义字段管理里面看),名称填写:(也在自定义字段管理里面),前缀:mp


内容模块入库表结构

内容模块表结构如下,demo模块为例,

dr_表示数据表前缀

1表示站点id号

demo表示模块目录

其中后缀_0的表属于附表,会按10w数据量来分表递增


二次开发手动入库至少要入库这几个表

1、【独立模块忽略】如果demo模块是共享模块的话,入库共享索引表:dr_1_share_index 

此表第一个入库获取id索引号,以及存储demo目录,让宸逸cms识别这个id是demo模块的数据,出现内容页404现象

2、dr_1_demo_index 

【共享模块】需要将(1)中的id等数据写入到索引表中

【独立模块】直接生成新的id号及数据

3、dr_1_demo

模块内容的主表字段数据

其中有一个tableid字段是用于控制附表字段入库哪张表的,如果你不分表入库就设置为0

4、dr_1_demo_data_0

模块内容附表字段数据

这个_0后缀是由(3)中的tableid值决定


模块表单属性参数配置

每个模块模块都可以定义一种个性配置,为模块表单属性增加各种配置选项


例如,为demo模块的test表单,增加文本选项appid参数设置


1、新建模板dayrui/App/Demo/Views/diy_test.html


    appid
    
        
    

注意表单name的命名一定要是:data[setting][新的名称]



3、然后进入demo模块的网站表单里面找到

{xunruicms_img_title}


4、找到test表单,点击修改,切换到自定义设置,就可以看到了

{xunruicms_img_title}


5、读取这些参数的方式

A、程序中读取:

当前模块中时: $this->module['form']['test']['setting']['字段名']

B、模板中读取:

当前模块中时: {$ci->module['form']['test']['setting']['字段名']} (文本类型字段)



多个内容页:给内容创建多个模板和地址

需求:默认一篇内容只有一个地址和模板,就如【show-123.html】,这种地址表示内容详情页面;如果还需要为这个内容创建多个页面,例如【show-123-two.html】等。


实现原理:

使用新建控制器的方式来做新url地址构成。


实现方法:

1、以news模块为例,复制原有文件 dayrui/App/News/Controllers/Show.php

2、粘贴为Two.php,内容做一下变更:

_module_init();
        $data = $this->_Show(
            (int)\Phpcmf\Service::L('Input')->get('id'),
            [
                'field' => dr_safe_replace(\Phpcmf\Service::L('Input')->get('field')),
                'value' => dr_safe_replace(\Phpcmf\Service::L('Input')->get('value')),
            ],
            max(1, (int)\Phpcmf\Service::L('Input')->get('page')),
            1
        );
        
        // 这里指定新的模板
        \Phpcmf\Service::V()->display("show_two.html");
    }


}


3、默认访问地址就是这样:

/index.php?s=news&c=two&id=123


4、设置【show-123-two.html】格式的伪静态,打开config/rewrite.php追加:

"show\-([0-9]+)\-two\.html(.*)"  => 'index.php?s=news&c=two&id=$1',



-----------------------------

需要多加文件的话,可以重复【1~4】的步骤,并重新把two进行命名,改名字即可。

后台模块控制器继承重写

后台模块控制器的父类文件:

dayrui\App\Module\Control\Admin\Module.php 此控制器继承于Table类

此控制器作用是用于后台对模块的操作控制。


我们以Demo模块的用户中心模块控制器为例:

dayrui/App/Demo/Controllers/Admin/Home.php

其文件内容如下:

_Admin_List(true);
        // 这里写你的代码段
        return \Phpcmf\Service::V()->display($tpl);
    }

    public function add() {
        $tpl = $this->_Admin_Add(true);
        return \Phpcmf\Service::V()->display($tpl);
    }

    public function edit() {
        $tpl = $this->_Admin_Edit(true);
        return \Phpcmf\Service::V()->display($tpl);
    }

    public function show_index() {
        $this->_Admin_Show();
    }

    public function move_edit() {
        $this->_Admin_Move();
    }

    public function tui_edit() {
        $this->_Admin_Send();
    }

    public function syncat_edit() {
        $this->_Admin_Syncat();
    }

    public function del() {
        $this->_Admin_Del();
    }
}



用于内容模块的管理、添加、修改、删除动作的控制


如何继承修改父类的方法内容呢?因为父类控制器继承了Table类,那么子控制器也具备table类的继承属性