SHOPNC 插件机制的实现记录

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示例:

<?php
class MPAction{
        functiondoSomethings(&$args){
                echo"doSomethings:" . $args;
        }
}


 

 当然目前未做到尽善尽美,但基本在shopnc系统中实现了插件功能

 我的QQ:174487481,有兴趣的可以一起探讨

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、分销王环境要求 1、分销王系统因为涉及泛域名解析因此只能在公网上安装,无法在本地调试执行。 2、您应该拥有一台自己的服务器在公网,或者您可以修改apache的配置文件。 3、您必须拥有一个顶级域名,并对顶级域名进行设置,才可顺利安装分销王系统。 二、分销王环境配置方法(以shopnc.cn为例) 1、进入域名管理中将a记录设置为 *.shopnc.cn(例子域名)  ->对应ip 2、apache配置文件加入如下设置(举例,具体信息自行修改) <VirtualHost *:80>     ServerAdmin shopnc@gmail.com     DocumentRoot /var/www/html/juheshiyan/     ServerAlias  *.shopnc.cn </VirtualHost> 3、用www的域名开头安装如 www.shopnc.cn/install 主店后台管理路径:http://你的域名/system/ 子店后台管理路径:http://二级域名/admin/ 三、付款模式介绍 在安装过程中,需要您选择主店收款模式或子店收款模式,我们说明一下这两个模式。 1、主店收款模式:在此收款模式下,所有商品都由主店发布,子店无法发布商品。而是直接从主店发布的商品中选取合适的商品发布到自己的子店中。注册会员在各子店中购买商品,最终订单和收款由主店进行统一管理并处理。子店只能查看订单的处理情况,而无权处理订单。 2、子店收款模式:在此收款模式下,子店可以自由发布商品,主店只对子店发布的产品进行适当的监督。注册会员在子店中进行商品购买,最终订单和收款由子店自行处理。主店只能查看子店订单的处理情况,而无权处理订单。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值