|-wwwroot
| |-Addons [所有插件目录]
| | |-Editor [插件目录]
| | |-Controller [控制器目录,有URL访问的时候才需要,可选]
| | | |-UploadController.class.php [插件控制器,名字可以不和插件名一样]
| | |-config.php [配置文件, 有配置项的话可选]
| | |-content.html [插件模板页面,可选]
| | |-EditorAddons.class.php [插件定义和实现的文件,必须有!!]
| | |-[adminlist.html、config.html] [这些模板可选,用于自定义插件的配置页和列表页]目前仅介绍一下目录结构,在插件开发中将讲解每个文件如何定义。<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: yangweijie <yangweijiester@gmail.com> <code-tech.diandian.com>
// +----------------------------------------------------------------------
namespace Addons\Editor;
use Common\Controller\Addons;
/**
* 编辑器插件
* @author yangweijie <yangweijiester@gmail.com>
*/
class EditorAddons extends Addons{
public $info = array(
'name'=>'Editor',
'title'=>'前台编辑器',
'description'=>'用于增强整站长文本的输入和显示',
'status'=>1,
'author'=>'thinkphp',
'version'=>'0.1'
);
public function install(){
return true;
}
public function uninstall(){
return true;
}
/**
* 编辑器挂载的文章内容钩子
* @param array('name'=>'表单name','value'=>'表单对应的值')
*/
public function documentEditFormContent($data){
$this->assign('addons_data', $data);
$this->assign('addons_config', $this->getConfig());
$this->display('content');
}
/**
* 讨论提交的钩子使用编辑器插件扩展
* @param array('name'=>'表单name','value'=>'表单对应的值')
*/
public function topicComment ($data){
$this->assign('addons_data', $data);
$this->assign('addons_config', $this->getConfig());
$this->display('content');
}
}整个插件就是一个特殊的继承了 Addons抽象类的子类。必须实现 install和uninstall方法。 然后必须有一个自己的info属性,作为插件自己的信息。name、titile、desc /**
* 安装插件
*/
public function install(){
$addon_name = trim(I('addon_name'));
$addons = addons($addon_name);
if(!$addons)
$this->error('插件不存在');
$info = $addons->info;
if(!$info || !$addons->checkInfo())//检测信息的正确性
$this->error('插件信息缺失');
session('addons_install_error',null);
$install_flag = $addons->install();
if(!$install_flag){
$this->error('执行插件预安装操作失败'.session('addons_install_error'));
}
$addonsModel = D('Addons');
$data = $addonsModel->create($info);
if(is_array($addons->admin_list) && $addons->admin_list !== array()){
$data['has_adminlist'] = 1;
}else{
$data['has_adminlist'] = 0;
}
if(!$data)
$this->error($addonsModel->getError());
if($addonsModel->add($data)){
$config = array('config'=>json_encode($addons->getConfig()));
$addonsModel->where("name='{$addon_name}'")->save($config);
$hooks_update = D('Hooks')->updateHooks($addon_name);
if($hooks_update){
S('hooks', null);
$this->success('安装成功');
}else{
$addonsModel->where("name='{$addon_name}'")->delete();
$this->error('更新钩子处插件失败,请卸载后尝试重新安装');
}
}else{
$this->error('写入插件数据失败');
}
}实例化插件类->插件info是否正确->执行install方法,预安装操作->添加插件数据到数据库addons表和hooks表hooks('documentEditFormContent');然后hooks函数遍历 该钩子的addons字段,知道有哪些插件可被调用,接下来去读取配置和状态,启用就去执行钩子/**
* 处理插件钩子
* @param string $hook 钩子名称
* @param mixed $params 传入参数
* @return mixed
* @author 麦当苗儿 <zuojiazi@vip.qq.com>
*/
function hooks($hook, $params = array()) {
$hooks = S('hooks');
if(!$hooks){
$hooks = D('Hooks')->getField('name,addons');
foreach ($hooks as $key => $value) {
$hooks[$key] = explode(',', $value);
}
S('hooks',$hooks);
}
$addons = $hooks[$hook];
if(!empty($addons)) {
if(APP_DEBUG) {
G($hook.'Start');
trace('[ '.$hook.' ] --START--','','INFO');
}
// 执行插件
foreach ($addons as $key => $name) {
if($name){
$addons_class = addons($name);
if($addons_class){
$config = $addons_class->getConfig();
if(method_exists($addons_class, $hook) && $config['status'] == 1)
$addons_class->$hook($params);
} else {
trace("插件 {$name} 入口文件不存在",'ADDONS','ERR');
}
}
}
if(APP_DEBUG) { // 记录钩子的执行日志
trace('[ '.$hook.' ] --END-- [ RunTime:'.G($hook.'Start',$hook.'End',6).'s ]','','INFO');
}
}else{ // 未注册任何钩子 返回false
return false;
}
}#实例化一个插件类,我们有addons()函数,传入插件名即可,大小写区分
$addons_class = $addons($addon_name);这个方法就是去执行钩子处挂载的和钩子同名的插件方法。<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: yangweijie <yangweijiester@gmail.com> <code-tech.diandian.com>
// +----------------------------------------------------------------------
return array(
'editor_type'=>array(
'title'=>'编辑器类型:',
'type'=>'select',
'options'=>array(
'1'=>'普通文本',
'2'=>'富文本',
'3'=>'UBB解析',
'4'=>'Markdown编辑器'
),
'value'=>'1',
),
'editor_wysiwyg'=>array(
'title'=>'富文本编辑器:',
'type'=>'select',
'options'=>array(
'1'=>'Kindeditor',
'2'=>'Ueditor(百度编辑器)',
),
'value'=>1
),
'editor_height'=>array(
'title'=>'编辑器高度:',
'type'=>'text',
'value'=>'300px'
),
'editor_resize_type'=>array(
'title'=>'是否允许拖拉编辑器',
'type'=>'radio',
'options'=>array(
'0'=>'不允许',
'1'=>'允许'
),
'value'=>'1',
'tip'=>'ubb和markdown编辑器不支持此功能'
),
);数组的每个键都对应一个form表单。键名就是配置里会显示的表单名 并且为了防止冲突加了前缀 ,比如上面的editor_type 会显示为config[editor_type]。tireturn array(
'comment_type'=>array(//配置在表单中的键名 ,这个会是config[random]
'title'=>'使用类型:', //表单的文字
'type'=>'select', //表单的类型:text、textarea、checkbox、radio、select等
'options'=>array( //select 和radion、checkbox的子选项
'1'=>'有言', //值=>文字
'2'=>'多说',
),
'value'=>'1', //表单的默认值
),
'group'=>array(
'type'=>'group',
'options'=>array(
'youyan'=>array(
'title'=>'友言配置',
'options'=>array(
'comment_uid_youyan'=>array(
'title'=>'账号id:',
'type'=>'text',
'value'=>'90040',
'tip'=>'填写自己登录友言后的uid,填写后可进相应官方后台'
),
)
),
'duoshuo'=>array(
'title'=>'多说配置',
'options'=>array(
'comment_short_name_duoshuo'=>array(
'title'=>'短域名',
'type'=>'text',
'value'=>'',
'tip'=>'每个站点一个域名'
),
'comment_form_pos_duoshuo'=>array(
'title'=>'表单位置:',
'type'=>'radio',
'options'=>array(
'top'=>'顶部',
'buttom'=>'底部'
),
'value'=>'buttom'
),
'comment_data_list_duoshuo'=>array(
'title'=>'单页显示评论数',
'type'=>'text',
'value'=>'10'
),
'comment_data_order_duoshuo'=>array(
'title'=>'评论显示顺序',
'type'=>'radio',
'options'=>array(
'asc'=>'从旧到新',
'desc'=>'从新到旧'
),
'value'=>'asc'
)
)
)
)
)
);具体效果可以看社会化评论(SocialComment)插件的配置数组。见下图:ThinkPHP 是一个免费开源的,快速、简单的面向对象的 轻量级PHP开发框架 ,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内最领先和最具影响力的WEB应用开发框架,众多的典型案例确保可以稳定用于商业以及门户级的开发。