SHOPNC 插件机制的实现记录
来源:互联网 发布:广告宣传单设计软件 编辑:程序博客网 时间:2024/06/05 15:18
shopnc 是一款非常前卫的商城系统,功能强大
但这样一款强大的系统,遗憾是的没有插件体制,如果想要什么新功能,就都得修改源文件,会很不方便
作为码农,我是这样想的,给她一个插孔,让很多人插
/global.php 添加:
defined('DIR_PLUGINS') ||define('DIR_PLUGINS',BASE_ROOT_PATH.'/plugins');//added by bruce.chou 2016-5-24
建立/core/plugins.php:
<?php/*** shopnc 插件管理类* @author bruce.chou @2016-5-25***/defined('InShopNC') or exit('AccessInvalid!'); defined('PLUGIN_EVENT_1') ||define('PLUGIN_EVENT_1','PLUGIN_EVENT_1'); class Plugins{ /** * 保存所有插件 */ publicstatic $all_plugins = array(); /** *取得所有插件 * */ static function get_plugins(){ $result = array(); if($dh = opendir(DIR_PLUGINS)){ while(($f= readdir($dh)) !== false) { if($f != '.' && $f != '..'&& is_dir($cur = DIR_PLUGINS.'/'.$f)) { if($cfg = require($cur ."/config.php")) { //if($cfg['active']){ $cfg['path']= $cur; //记录插件的安装目录 $result[$f]= $cfg; //} } } } closedir($dh); } return self::$all_plugins=$result; } /** *@description 供插件的视图中调用用于显示插件目录下的模板 *@author bruce.chou 2016-5-25 *@param string $page_name 要显示的模板文件 *@param string $layout 要包含的布局文件 *@param object $plugin 插件对象 *//@ string$obj_plugin->module_name 要加载的模块如 admin,home,salers,mobile等 */ publicstatic function tpl_showpage($page_name,$layout='',$obj_plugin=NULL ){ if(!empty($obj_plugin->plugin_name)) { if(array_key_exists($obj_plugin->plugin_name,self::$all_plugins)){ $path= $obj_plugin->plugin_path.'/'.$obj_plugin->module_name; //echo$path; Tpl::output("this_plugin",$obj_plugin); Tpl::showpage($page_name,$layout,2000,$path); }else{ exit("$obj_plugin->plugin_namenot found in plugins array"); } } else{ exit("lostplugin_name for show page!"); } } /*函数转发*/ publicstatic function tpl_output($arg='',$args){ Tpl::output($arg,$args); } publicstatic function triger_event($evt,&$args){ foreach(self::$all_plugins as $key => $value) { foreach($value['listen'] as $e => $f) { if($e==$evt){ $path= DIR_PLUGINS . '/' . $key . '/action.php'; $cls= ucwords($key)."Action"; if(file_exists($path)){ require_once($path); $action_cls= new $cls(); if(method_exists($action_cls,$f)){ $action_cls->$f($args); } } } } } } publicstatic function url($obj_plugin,$act='',$op='',$args=array()){ //plugin-mp-admin-mb_mpweixin returnurl("plugin-".$obj_plugin->plugin_name.'-'.$obj_plugin->module_name.'-'.$act,$op,$args); } }$all_plugins = Plugins::get_plugins();
插件目录设定在/plugins/插件名
目录结构:
插件名/
config.php //插件配置文件
action.php //插件监听处理类
models/ ->模型类目录
数据库交互处理功能文件列表
admin/ ->后台功能
control/
控制器文件列表
templates/
视图文件列表
home/ ->前台功能
control/
控制器文件列表
templates/
视图文件列表
mobile/ //手机端功能
…
salers/ ->商户后台功能
…
修改过的原始核心文件:
/core/base.php
/**
* 控制器调度
*
*/
privatestatic function control(){
//二级域名
if($GLOBALS['setting_config']['enabled_subdomain'] == '1' && $_GET['act']== 'index' && $_GET['op'] == 'index'){
$store_id= subdomain();
if($store_id > 0) $_GET['act'] = 'show_store';
}
/*
addedby bruce.chou 2016-5-24
*/
$act= trim($_GET['act']);//'plugin.mp.mb_mpweixin', //方法名 method
$m=array();
if(strpos($act,'plugin-') === 0){
//echoBASE_ROOT_PATH.$act;
$m = explode("-",$act);
//print_r($m);
$act_file = (BASE_ROOT_PATH.'/plugins/'.$m[1].'/'.$m[2].'/control/'.$m[3].'.php');
$_GET['act'] = $m[3];
}else{
$act_file= realpath(BASE_PATH.'/control/'.$_GET['act'].'.php');
}
//bybruce.chou
//die($act_file);
$class_name= $_GET['act'].'Control';
if(!@include($act_file)){
if (C('debug')) {
throw_exception("Base Error:access file isn't exists!");
} else {
showMessage('抱歉!您访问的页面不存在','','html','error');
}
}
if(class_exists($class_name)){
$main= new $class_name();
//bybruce.chou 2016-5-25 给实例类添加动态属性 插件名,插件路径
if(!empty($m)){
$main->plugin_name= $m[1];
$main->plugin_path= BASE_ROOT_PATH.'/plugins/'.$m[1];//.'/'.$m[2];
$main->module_name= $m[2];
$main->act = $_GET['act'];
}
$function= $_GET['op'].'Op';
if(method_exists($main,$function)){
$main->$function();
}elseif(method_exists($main,'indexOp')){
$main->indexOp();
}else{
$error= "Base Error: function $function not in $class_name!";
throw_exception($error);
}
}else{
$error= "Base Error: class $class_name isn't exists!";
throw_exception($error);
}
}
/core/framework/libraries/tpl.php
其实就是新增参数$base_p
* 调用显示模板
*
* @param string $page_name
* @param string $layout
* @param int $time
*/
publicstatic functionshowpage($page_name='',$layout='',$time=2000,$base_p=BASE_PATH){
if(!defined('TPL_NAME')) define('TPL_NAME','default');
self::getInstance();
if(!empty(self::$tpl_dir)){
$tpl_dir= self::$tpl_dir.DS;
}
//默认是带有布局文件
if(empty($layout)){
$layout= 'layout'.DS.self::$layout_file.'.php';
}else{
$layout= 'layout'.DS.$layout.'.php';
}
$layout_file= $base_p.'/templates/'.TPL_NAME.DS.$layout;
$tpl_file= $base_p.'/templates/'.TPL_NAME.DS.$tpl_dir.$page_name.'.php';
//echo $layout_file." >$tpl_file";
if(file_exists($tpl_file)){
//对模板变量进行赋值
$output= self::$output_value;
//页头
$output['html_title']= $output['html_title']!='' ? $output['html_title']:$GLOBALS['setting_config']['site_name'];
$output['seo_keywords']= $output['seo_keywords']!='' ? $output['seo_keywords']:$GLOBALS['setting_config']['site_name'];
$output['seo_description']= $output['seo_description']!='' ? $output['seo_description']:$GLOBALS['setting_config']['site_name'];
$output['ref_url']= getReferer();
Language::read('common');
$lang= Language::getLangContent();
@header("Content-type:text/html; charset=".CHARSET);
//判断是否使用布局方式输出模板,如果是,那么包含布局文件,并且在布局文件中包含模板文件
if($layout != ''){
if(file_exists($layout_file)){
include_once($layout_file);
}else{
$error= 'Tpl ERROR:'.'templates'.DS.$layout.' is not exists';
throw_exception($error);
}
}else{
include_once($tpl_file);
}
}else{
$error= 'Tpl ERROR:'.'templates'.DS.$tpl_dir.$page_name.'.php'.' is not exists';
throw_exception($error);
}
}
修改/core/shopnc.php
//统一ACTION 添加 - 号为合法 bybruce.chou 2016-5-24
$_GET['act'] =preg_match('/^[\w\-]+$/i',$_GET['act']) ? $_GET['act'] : 'index';
$_GET['op'] =preg_match('/^[\w\-]+$/i',$_GET['op']) ? $_GET['op'] : 'index';
并在未处添加
//by bruce.chou
if(file_exists(BASE_CORE_PATH."/plugins.php")){
include(BASE_CORE_PATH."/plugins.php");
}
插件目录下/config.php示例:
<?php defined('InShopNC') or exit('AccessInvalid!'); return array( 'name' => 'mp', 'description' => '微信端功能扩展,提供后台界面,微信交互处理等', 'active'=>'1', //指示插件是否为活动状态 'install'=>'install.php', //安装文件,应该有MP_INSTALL类实现 install 和 uninstall方法 'listen' => array( PLUGIN_EVENT_1=>'doSomethings', //要监听的事件数组 ), 'menu'=> array( 'top' => 'mobile', //顶层KEY,如果存在原有的将会新增 'text'=> '微信端', //顶层菜单显示的名字,此参数仅在是新的顶层菜单会使用,如果是已存在的,则会忽略 'left'=> array( array( 'act'=>'plugin-mp-admin-mb_mpweixin', //模块名必须以plugin开头+plugin名称+目录名+control 'op'=>'mb_mpweixin', //方法名 method 'nav'=>'mobile', //必须和顶层KEY一样 'text'=>'微公众号', //在左边要显示的名称 ), /*array( 'op'=>'mb_mpweixin', //模块名 control 'act'=>'mb_mpweixin1', //方法名 method 'nav'=>'mobile', //必须和顶层KEY一样 'text'=>'微公众号1', //在左边要显示的名称 ),*/ ), ), 'limit'=> array('name'=>$lang['nc_mobile'], 'child'=>array( array('name'=>'微公众号', 'op'=>NULL,'act'=>'mb_mpweixin'), )) );
添加菜单到后台操作:
/* @bybruce.chou 2016-5-24 读取所有插件并加入到管理菜单中 **/ global$all_plugins; $plugins= $all_plugins;//Plugins::get_plugins(); foreach($plugins as $key => $value) { //查找顶层菜单,如果未找到则添加顶层菜单 $found= -1; foreach($array['top'] as $k=>$v) { if($v['args']== $plugins[$key]['menu']['top'] ){ $found= $k; //找到的话记住KEY } } if($found == -1 ){ $array['top'][]= array('args' => $plugins[$key]['menu']['top'] ,'text'=>$plugins[$key]['menu']['text'] ); $found= count($array['top']) - 1; $array['left'][]= array('nav' => $plugins[$key]['menu']['top'], 'text'=>$plugins[$key]['menu']['text'] ); } foreach($plugins[$key]['menu']['left'] as $i => $j) { #code... $array['left'][$found]['list'][]= array( 'args' => $j['op'] . ',' . $j['act'] ."," . $j['nav'], 'text' => $j['text'], ); } } /*by bruce.chou*/
在插件任何目录下的控制器类中要显示相关视图:
Plugins::tpl_output('变量名', $变量);
Plugins::tpl_showpage('视图文件','布局文件',$this );
插件目录/action.php示例:
<?phpclass MPAction{ functiondoSomethings(&$args){ echo"doSomethings:" . $args; }}
当然目前未做到尽善尽美,但基本在shopnc系统中实现了插件功能
我的QQ:174487481,有兴趣的可以一起探讨
- SHOPNC 插件机制的实现记录
- shopnc跳转WAP端的实现方法
- shopnc josn实现方式
- NET的插件机制的简单实现
- 如何用实现.NET的插件机制
- 灵活正确的实现.NET插件机制
- 灵活正确的实现.NET插件机制
- 灵活正确的实现.NET插件机制
- 用Windsor实现.Net的插件机制
- 灵活正确的实现.NET插件机制
- php实现网站插件机制的方法
- 插件机制的实现核心类
- ShopNC的创业之路
- shopnc模型的坑点
- shopnc 实现手机、邮箱、用户名登录
- 关于.net编译过后的程序增加功能的一种实现方式_也可以说是.net exe注入,插件机制_开发记录
- 转:ShopNC的创业之路
- 常用的shopNC部分大写字母函数
- codeforces56
- 惊人之鸣(2006.12.10)
- how to install window exe program on ubuntu
- Git Base 操作
- android自定义控件系列
- SHOPNC 插件机制的实现记录
- epoll的LT、ET模式和EPOLLONESHOT事件实例介绍
- 【NOIP2013模拟】Freda的传呼机
- UI控件大全
- 2.6 MYSQL的输出格式
- LeetCode题解——House Robber III
- codeforces58
- I/O复用之 select和epoll
- 欢迎使用CSDN-markdown编辑器