ThinkPHP5中如何加入插件功能
加入插件的方法:
1、在系统的index.php入口中加入如下配置
// 插件目录
define('ADDON_PATH', __DIR__ . '/../addons/');
// 开启系统行为
define('APP_HOOK', true);
2、在数据库中加入addons插件表和hooks钩子表
CREATE TABLE `addons` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(40) NOT NULL COMMENT '插件名或标识',
`title` varchar(20) NOT NULL DEFAULT '' COMMENT '中文名',
`description` text COMMENT '插件描述',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态',
`config` text COMMENT '配置',
`author` varchar(40) DEFAULT '' COMMENT '作者',
`version` varchar(20) DEFAULT '' COMMENT '版本号',
`create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '安装时间',
`has_adminlist` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否有后台列表',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='插件表';
CREATE TABLE `hooks` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(40) NOT NULL DEFAULT '' COMMENT '钩子名称',
`description` text NOT NULL COMMENT '描述',
`type` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '类型',
`update_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
`addons` varchar(255) NOT NULL DEFAULT '' COMMENT '钩子挂载的插件 '',''分割',
`status` tinyint(2) DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
3、在ThinkPHP5的根目录中创建addons目录
www WEB项目目录
├─composer.json composer定义文件
├─README.md README文件
├─LICENSE.txt 授权说明文件
├─addons 插件目录(新增)
├─application 应用目录
│ ├─common 公共模块目录(可以更改)
│ ├─runtime 应用的运行时目录(可写,可定制)
│ ├─module 模块目录
│ │ └─ ... 更多类库目录
│ ├─common.php 公共函数文件
│ ├─config.php 公共配置文件
│ ├─route.php 路由配置文件
│ └─database.php 数据库配置文件
│
├─public WEB目录(对外访问目录)
│ ├─index.php 入口文件
│ ├─.htaccess 用于apache的重写
│ └─router.php 快速测试文件(用于PHP内置webserver)
│
├─thinkphp 框架系统目录
4、在application中的common.php公共函数里添加两个公共方法
/**
* 获取插件类的类名
* @param strng $name 插件名
* @param string $ext 扩展名
*/
function get_addon_class($name, $ext = EXT)
{
// 初始化命名空间及类名
$class = "addons\\{$name}\\" . ucfirst($name);
return $class;
}
/**
* 处理插件钩子
* @param string $hook 钩子名称
* @param mixed $params 传入参数
* @return void
*/
function hook($hook, $params = [])
{
// 钩子调用
\think\Hook::listen($hook, $params);
}
5、在application目录下创建common模块,在common模块中创建behavior行为目录,在公共行为目录中创建Hooks.php钩子行为插件,内容如下:
<?php
// +----------------------------------------------------------------------
// | zzstudio [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://www.zzstudio.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Byron Sampson <xiaobo.sun@gzzstudio.net>
// +----------------------------------------------------------------------
namespace app\common\behavior;
use think\Hook;
class Hooks
{
public function run(&$param = [])
{
if(defined('BIND_MODULE') && BIND_MODULE === 'Install') return;
// 动态加入命名空间
\think\Loader::addNamespace('addons', ADDON_PATH);
// 获取钩子数据
$data = S('hooks');
if(!$data){
$hooks = M('Hooks')->getField('name,addons');
// 获取钩子的实现插件信息
foreach ($hooks as $key => $value) {
if($value){
$map['status'] = 1;
$names = explode(',',$value);
$map['name'] = ['IN', $names];
$data = M('Addons')->where($map)->getField('id,name');
if($data){
$addons = array_intersect($names, $data);
Hook::add($key, array_map('get_addon_class', $addons));
}
}
}
S('hooks', Hook::get());
}else{
Hook::import($data, false);
}
}
}
6、在application目录中创建tags.php行为配置文件,并且加入内容
<?php
// 系统行为定义
return [
'app_init' => [
'app\\common\\behavior\\Hooks'
],
'action_begin'=> [
],
'app_end'=> [
]
];
到此为止,插件功能就集成完毕了。
接下来我们做个简单的插件试一下:
1、在addons目录中创建一个Base.php 插件的基类
<?php
// +----------------------------------------------------------------------
// | addons [ WE CAN DO IT JUST ZZSTUDIO IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2015 http://www.zzstudio.net All rights reserved.
// +----------------------------------------------------------------------
// | Author: byron sampson <xiaobo.sun@zzstudio.net>
// +----------------------------------------------------------------------
namespace addons;
/**
* 插件类
* @author byron sampson <xiaobo.sun@zzstudio.net>
*/
abstract class Base{
/**
* 视图实例对象
* @var view
* @access protected
*/
protected $view = null;
/**
* $info = array(
* 'name'=>'Editor',
* 'title'=>'编辑器',
* 'description'=>'用于增强整站长文本的输入和显示',
* 'status'=>1,
* 'author'=>'thinkphp',
* 'version'=>'0.1'
* )
*/
public $info = array();
public $addon_path = '';
public $config_file = '';
public $custom_config = '';
public $admin_list = array();
public $custom_adminlist = '';
public $access_url = array();
/**
* 基类构造函数
* Base constructor.
*/
public function __construct()
{
$this->view = new \think\View();
$this->addon_path = ADDON_PATH . $this->getName() . '/';
$TMPL_PARSE_STRING = C('parse_str');
$TMPL_PARSE_STRING['__ADDONROOT__'] = $TMPL_PARSE_STRING['__ADDONS__'] . '/' . $this->getName();
C('parse_str', $TMPL_PARSE_STRING);
if(is_file($this->addon_path . 'config.php')){
$this->config_file = $this->addon_path . 'config.php';
}
}
/**
* 模板主题设置
* @access protected
* @param string $theme 模版主题
* @return Action
*/
final protected function theme($theme)
{
$this->view->theme($theme);
return $this;
}
/**
* 模板变量赋值
* @access protected
* @param mixed $name 要显示的模板变量
* @param mixed $value 变量的值
* @return Action
*/
final protected function assign($name, $value='')
{
$this->view->assign($name,$value);
return $this;
}
//用于显示模板的方法
final protected function fetch($templateFile = CONTROLLER_NAME)
{
if(!is_file($templateFile)){
$templateFile = $this->addon_path . $templateFile . ".html";
if(!is_file($templateFile)){
E(L('_TEMPLATE_NOT_EXIST_') . ":$templateFile");
}
}
return $this->view->fetch($templateFile);
}
/**
* 获取插件名
* @return string
*/
final public function getName()
{
$class = get_class($this);
list($space, $name, $class) = explode('\\', $class);
return $name;
}
/**
* 检查配置信息是否完整
* @return bool
*/
final public function checkInfo()
{
$info_check_keys = array('name','title','description','status','author','version');
foreach ($info_check_keys as $value) {
if(!array_key_exists($value, $this->info))
return false;
}
return true;
}
/**
* 获取插件的配置数组
*/
final public function getConfig($name = '')
{
static $_config = [];
if(empty($name)){
$name = $this->getName();
}
if(isset($_config[$name])){
return $_config[$name];
}
$map['name'] = $name;
$map['status'] = 1;
$config = M('Addons')->where($map)->getField('config');
if($config){
$config = json_decode($config, true);
}else{
$config = [];
$temp_arr = include $this->config_file;
foreach ($temp_arr as $key => $value) {
if($value['type'] == 'group'){
foreach ($value['options'] as $gkey => $gvalue) {
foreach ($gvalue['options'] as $ikey => $ivalue) {
$config[$ikey] = $ivalue['value'];
}
}
}else{
$config[$key] = $temp_arr[$key]['value'];
}
}
}
$_config[$name] = $config;
return $config;
}
/**
* 必须实现安装
* @return mixed
*/
abstract public function install();
/**
* 必须卸载插件方法
* @return mixed
*/
abstract public function uninstall();
}
2、在插件表(addons),钩子表(hooks)中加入相应的数据
INSERT INTO `addons` (`id`, `name`, `title`, `description`, `status`, `config`, `author`, `version`, `create_time`, `has_adminlist`) VALUES ('2', 'test', 'test插件', 'test插件简介', '1', NULL, 'byron sampson', '0.1', '1438154545', '0');
INSERT INTO .`hooks` (`id`, `name`, `description`, `type`, `update_time`, `addons`, `status`) VALUES ('21', 'demo', 'demo钩子', '1', '1384481614', 'test', '1');
3、在addons目录中创建一个test目录,且内部创建一个Test.php插件类
<?php
// +----------------------------------------------------------------------
// | test [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://www.zzstudio.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Byron Sampson <xiaobo.sun@gzzstudio.net>
// +----------------------------------------------------------------------
namespace addons\test;
class Test extends \addons\Base
{
/**
* 实现demo钩子
* @param array $params
*/
public function demo($params = [])
{
echo 'demo hook!page is ' . $params['p'];
}
/**
* 安装方法
*/
public function install()
{
// TODO: Implement install() method.
}
/**
* 卸载方法
*/
public function uninstall()
{
// TODO: Implement uninstall() method.
}
}
4、在控制器中使用hook方法来调用钩子
hook('demo', ['p'=>'page']);
5、ok,大功告成
来源:https://blog.zzstudio.net/bs/article_888.html