# 四、模块开发教程
1.模块的安装卸载机制介绍
OC的模块安装机制目前来说比较简单,暂时只支持本地模块的安装卸载。
如果要能够被OC识别并允许安装卸载。开发人员需要遵守以下约定。
目录结构约定:
模块文件放置在
/Application下
每一个模块的目录结构如下
以Issue(专辑)模块为例
/Conf 配置文件 config.php 模块配置文件
/Controller 控制器
IndexController 模块入口控制器
IssueController 模块管理后台控制器
/Info 模块信息
info.php 模块信息
install.sql 模块安装sql
uninstall.sql 模块卸载sql
/Model 业务模型
IssueModle.class.php Issue模块
/Static 静态资源存放
/css
/js
/View 模板文件
/defalut
/Index
index.html 模块首页模板
/Public
/Widget
ueditormini.html UeditorMini编辑器小部件模板
/Widget 小部件Widget
UeditorMiniWidget.class.php UeditorMini编辑器小部件控制器
模块的生命周期:
1.安装模块
2.使用模块
3.卸载模块
安装模块
此步骤涉及到/Info/info.php
<?php
return array(
//模块名
'name' => 'Issue',
//别名
'alias' => '专辑',
//版本号
'version' => '1.0.0',
//是否商业模块,1是,0,否
'is_com' => 0,
//是否显示在导航栏内? 1是,0否 暂时无效,保留项
'show_nav' => 1,
//模块描述
'summary' => '专辑模块,适用于精品内容展示',
//开发者
'developer' => '嘉兴想天信息科技有限公司',
//开发者网站
'website' => 'http://www.ourstu.com',
//前台入口,可用U函数
'entry' => 'Issue/index/index',
//后台入口
'admin_entry' => 'Admin/Issue/contents',
//zui中的icon-xxx的小图标,此处为icon-th
'icon' => 'th',
//是否允许卸载,核心模块请设为0
'can_uninstall' => 1
);
上面代码定义了专辑模块的模块信息,显示在模块管理中的内容为
可以点击安装按钮执行安装。
安装的过程就是导入/Info/install.sql这个数据表。
安装成功后,左侧模块列表中会多出一个模块。图标就是info.php中的th。链接地址就是Admin/Issue/contents
卸载模块
同时可以通过卸载按钮卸载文件。
卸载模块其实就是执行了uninstall.sql这个操作。
2.模块的开发
OC中多模块的开发实际上和普通的TP模块开发是一致的。这边主要介绍一下OC中的一些机制,这些机制会大大降低开发成本。
<?php
namespace Admin\Controller;
use Admin\Builder\AdminConfigBuilder;
use Admin\Builder\AdminListBuilder;
use Admin\Builder\AdminTreeListBuilder;
class IssueController extends AdminController
{
protected $issueModel;
function _initialize()
{
$this->issueModel = D('Issue/Issue');
parent::_initialize();
}
public function config()
{
$admin_config = new AdminConfigBuilder();
$data = $admin_config->handleConfig();
$admin_config->title('专辑基本设置')
->keyBool('NEED_VERIFY', '投稿是否需要审核','默认无需审核')
->buttonSubmit('', '保存')->data($data);
$admin_config->display();
}
public function issue()
{
//显示页面
$builder = new AdminTreeListBuilder();
$attr['class'] = 'btn ajax-post';
$attr['target-form'] = 'ids';
$attr1 = $attr;
$attr1['url'] = $builder->addUrlParam(U('setWeiboTop'), array('top' => 1));
$attr0 = $attr;
$attr0['url'] = $builder->addUrlParam(U('setWeiboTop'), array('top' => 0));
$tree = D('Issue/Issue')->getTree(0, 'id,title,sort,pid,status');
$builder->title('专辑管理')
->buttonNew(U('Issue/add'))
->data($tree)
->display();
}
}
3.管理后台菜单的创建
模块在被安装之后,会自动在左侧菜单创建一个入口(要求模块的配置信息中admin_entry不为空),这个入口是不需要菜单机制配合的。系统会自动添加。
但是,开发者在开发后台管理界面的时候往往需要用到侧栏菜单,这就需要开发者手动创建一些菜单来实现这个功能。为了兼容原生的菜单机制,我们采用了如下的变通方法来实现侧栏菜单。
1.针对某个模块创建一个隐藏的顶级菜单项,一般命名为模块名称。如Issue里,我们先要创建一个如图所示的顶级菜单项(这一步必不可少)
创建菜单的入口为 用户-》权限(分组)-》菜单-》新增
图中链接是默认的一个地址,建议和模块的后台管理入口一致,是否隐藏设为是,如果不设为是,就会在顶部栏多出一个入口
2.创建顶级菜单项之后再创建二级菜单。
上述创建的菜单会在侧栏菜单产生这么一个菜单项
在菜单管理的过程中,我们有以下两点建议,也算是开发过程中的一些经验总结。
1.对于有表单的页面,强烈建议提交到当前页面,再用IS_POST去判断是表单提交还是普通的展示表单。
此建议好处在于可以少创建一个菜单来专门用于权限处理。不需要为展示表单和处理表单创建两个权限节点。
2.对于一些ajax操作,必须为相应ajax操作的action创建对应的隐藏节点来处理权限。
因为OC中,后台的权限默认是用菜单来实现绑定,所以一些隐藏的菜单项实际上就是一个权限节点的存在。
如果开发者不针对一些ajax请求访问的action去创建隐藏菜单的话,很容易出现给了某些管理员的列表页面的管理权限之后却没有操作的权限。
3.用AdminConfigBuilder创建一个配置页面
在日常研发中,开发人员难以避免地要创建一些管理页面,比较常见的就是配置页面,这类页面的创建,OC提供了一套简单的方案。也就是很多OC开发达人一直在用的的AdminBuilder系列类库。
这边就不详讲这个类库了,详细的大家看手册吧。我这边就讲一下一般的ConfigBuilder的用法。
考虑到Issue模块的ConfigBuilder太过简单,这边我以OpenSNS的新版首页模块Home为例,讲一个较为复杂的Config。
1).创建代码文件
这边涉及到一个知识点,就是模块的AdminController的一个内部约定,遵守这个约定可以让模块的文件更加聚合,但如果你不遵守,同样也能实现功能,缺点就是文件不聚合。
方法一、不遵守约定,我们首先要在Admin模块的Controller里创建一个HomeController,这个Controller务必需要继承AdminController,因为有很多东西要处理,AdminContoller会自动处理。
方法二、遵守约定,我们在Home模块的Controller里创建一个HomeController,同样继承自AdminController。
知识点
方法一的定义和方法二的代码文件必须一致。文件内容完全不受文件位置影响。
这边再额外废话一句,为什么放在不同的位置结果都是一样的呢?因为OC做了一个重定向,方法一种,文件就在AdminController下,这是最符合后台的机制的方式。但是,OC考虑到模块文件的聚合,提出了方法二,方法二实现原理就是在Admin模块的EmptyController的empty方法里,去做了检测,如果发现访问的页面不存在,就会去实例对应模块的对应Controller的对应action。
这边以Home为例
index.php?s=/admin/home/config.html
上面这个Url按照传统方式,定位点为Application/Admin/Controller/HomeController.class.php的config()方法
按照方法二的存放方式,系统会发现这个定位点不存在。接下来系统会尝试去实例Application/Home/Controller/HomeController.class.php的config()方法,如果存在就调用。
实际上,方法二只是把文件移动到了Home模块下,让所有的文件都放到这个模块里,增强模块内聚。
文件创建好了之后,我们就需要写内部实现代码了。
2).书写代码
基本结构
namespace Admin\Controller;
use Admin\Builder\AdminConfigBuilder;
class HomeController extends AdminController{
public function config() {
}
}
命名空间采用Admin\Controller,原因上面讲过了。
use只是为了引入AdminConfigBuilder下面备用。
接下来,我们实例化一个AdminConfigBuilder。
代码
1 $builder = new AdminConfigBuilder();
定义管理页面的标题,调用builder的title方法
1 $builder->title('首页设置');
到这里。页面基本框架已经构建好了。
直接访问index.php?s=/admin/home/config.html显示如图
接下来,我们开始加入各种配置项。
通过加入这些代码,我们能创建一个如图所示的配置页面
$builder->keySingleImage('LOGO', 'Logo图标', '此处不同于网站信息内的LOGO,只在首页显示');
$builder->keyRadio('OPEN_LOGIN_PANEL', '开启登陆面板', '关闭则不显示登陆面板', array(1 => '开启', 2 => '关闭'));
$builder->keyText('ENTER_URL', '随便看看Url','不填则隐藏此按钮,不留入口,支持形如weibo/index/index之类的tp写法和http://等常规写法');
$builder->keyEditor('SUMMARY', '导语', '顶部导语,用一句话来介绍你的网站');
$builder->group('内容设置', 'LOGO,SUMMARY,OPEN_LOGIN_PANEL,ENTER_URL');
首先,我们要明确,在builder里面,我们一般会用keyXXX的函数来创建页面的表单元素。
1 $builder->keySingleImage('LOGO', 'Logo图标', '此处不同于网站信息内的LOGO,只在首页显示');
上面这条代码,是创建一个单图上传,第一个参数是表单元素的name,也就是提交到后台的表单键名,第二个参数是在页面中显示的字段标题,第三个是辅助文字。
此类的方法有很多。这边就不祥解了。着重提一提group()方法。
group()方法可以实现对配置项的分组,这个方法有两种定义方式。
1 public function group($name,$list = array())
1 public function groups($list = array())
第一种,只能定义一个配置项分组
第二种能实现多个配置项分组的同时定义
如
1 $builder->group('内容设置', 'LOGO,SUMMARY,OPEN_LOGIN_PANEL,ENTER_URL');
就定义了一个配置项分组——内容设置,其下有LOGO,SUMMARY,OPEN_LOGIN_PANEL,ENTER_URL这几个key。
以此类推。我们可以定义多个配置项分组。
代码结构
$builder->keyXXX();
$builder->keyXXX();
$builder->group();
---------组1--------
$builder->keyXXX();
$builder->keyXXX();
$builder->group();
---------组2--------
$builder->keyXXX();
$builder->keyXXX();
$builder->group();
---------组3--------
最后,我们还需要加入一个保存按钮。保存按钮使用代码创建就是
1 $builder->buttonSubmit();
最后的最后,我们还需要展示这个界面
1 $builder->display();
好了。大功告成。